← NightshiftCONTENT HISTORY

Update to Nightshift

Snapshot Sep 30, 2026 · 23:14 UTC · version 0.25.3

Collection source: not recorded for this historical snapshot.

WHAT CHANGED · RULE-BASED ANALYSIS

First saved snapshot

No earlier snapshot is available to establish a change.

Compare saved observations

Download comparison JSON
Full technical diff · 0 changed fields
Full snapshot data
{
  "description": "Scaffold .nightshift/ and propose quality gates for this stack; asks, never imposes.",
  "included_files": [],
  "name": "setup",
  "skill_md_contents": "---\nname: setup\ndescription: Scaffold .nightshift/ and propose quality gates for this stack; asks, never imposes.\nlicense: MIT\n---\n\nSet up Nightshift in this project. Do the scaffolding first, then the gates conversation, then\nprint a summary.\n\nThe four state files and what each holds are in\n`$NIGHTSHIFT_PLUGIN_ROOT/skills/nightshift/references/shift/state-map.md`. Ordinary plans belong in the drafting table, never in Hunt or the parking lot.\n\nResolve the installed plugin root to an absolute `$NIGHTSHIFT_PLUGIN_ROOT` — `${CLAUDE_PLUGIN_ROOT}`\non Claude Code, `$PLUGIN_ROOT` on Codex when set, otherwise the absolute path this skill was\nattached from (`skills/setup/SKILL.md`). Run every command below through\n`\"$NIGHTSHIFT_PLUGIN_ROOT/runtime/ns\"` — native Windows: `& \"$NIGHTSHIFT_PLUGIN_ROOT\\runtime\\windows\\ns.ps1\"`\nin the PowerShell tool, same verbs — which resolves the host and the workspace; `ns help` lists the\nverbs, and `ns bind` prints the six resolved facts (`TASK_ROOT`, `NIGHTSHIFT_WORKSPACE`, `NS`,\n`NIGHTSHIFT_PLUGIN_ROOT`, `HOST`, `SOURCE`); `$NS` below is that `NS`. Never a bare relative path: the working\ndirectory persists between calls. Each `$NS/...` path below is where the current layout keeps that file;\n`ns path <key>` prints where this workspace keeps it, and `ns path --list` names every key.\n\nOnce the workspace and work target are resolved, the bundled mechanical scaffold is\n`ns setup --work-target \"$WORK_TARGET\" --mode \"$WORK_MODE\"`, which exists on native Windows only;\non every other host this skill writes the same templates itself, as below.\nIt copies only absent files, writes state version 2 for a new site, persists the work target and\nwork mode (`-Mode repository` or `-Mode artifact`), and keeps `$NS/` private. It refuses a notes\nfolder under default repository mode: `use -Mode artifact for a notes folder that is not a Git repository`.\nOn an existing site at an older state-version its `migration` field describes the move into the\ncurrent layout, exactly as the preview below would. Read its output back rather than restating it.\nThe skill still owns every owner choice below; the\nscript asks nothing and never invents gates, permissions, profiles, migration approval, a receipts\nchoice, or a tooling policy.\n\nIf the user explicitly identifies a different existing workspace containing `.nightshift/`, show\nboth absolute paths and ask for confirmation. On yes, run\n`\"$NIGHTSHIFT_PLUGIN_ROOT/runtime/ns\" link-workspace --host-root \"$TASK_ROOT\" --workspace \"$PROPOSED_WORKSPACE\"`.\nThe pointer is local-only and state remains in the authoritative workspace; never copy it.\n\n## 0. Reject disposable ChatGPT scratch workspaces\n\nBefore creating or changing any file, resolve the project root to an absolute path. If it is under\n`/workspace/scratch/`, this is a disposable ChatGPT scratch workspace that cannot affect the user's\nrepository. **Stop immediately: create no `$NS/` directory, rules, settings, receipts repo,\nor other files.** Tell the user directly:\n\n> Nightshift needs a persistent software project workspace. This ChatGPT conversation is using a\n> temporary workspace, so files created here will not affect your repository.\n>\n> Open your project in Codex (a Git repository or a persistent local folder), or start Codex connected to its GitHub repository. Then mention\n> Nightshift and say: “Set up Nightshift in this project.”\n\nDo not mention Claude Code in this ChatGPT-specific redirect: the user is already in an OpenAI\nproduct, so give them the shortest OpenAI-native route. Do not infer “temporary” merely because the\nproject is not a git repository — local non-git projects and the recommended parent-workspace\nlayout remain valid. The explicit disposable scratch path is the stop signal.\n\nDetect the work mode, explain it, and ask before persisting it. Use\n`ns_propose_work_mode` (POSIX) or `Get-NSProposedWorkMode` after importing\n`Nightshift.psm1` (native Windows):\n\n- `repository` — the workspace is a Git repository, or exactly one immediate non-hidden child is. Skip a symlink or reparse child; it is not a nested checkout.\n  several child repositories still mean repository mode; show the choices and require an explicit\n  target, never guess.\n- `artifact` — there is no Git repository here. The persistent folder itself is the work target\n  (research, docs, audits, planning). Say so plainly: gates, commits, and stack detection that\n  require Git do not apply; complete each item with a receipt under `$NS/receipts/`.\n  Completion in that folder is `$NS/receipts/`, not a git log.\n  When `$NS/receipts` exists but is not a usable directory, say so and do not treat artifact setup as complete.\n- scratch (`ns_propose_work_mode` status 2, or `Get-NSProposedWorkMode` throwing) — stop; create\n  nothing.\n\nNever persist a mode until the owner confirms. Never `git init` a notes folder to change an artifact proposal into repository mode. Then write `$NS/run/work-mode` as `repository` or\n`artifact` (one word, one newline) and `$NS/run/work-target` as the absolute canonical path of the\nchosen folder. On POSIX: `ns_record_work_target \"$NIGHTSHIFT_WORKSPACE\" \"$WORK_TARGET\" \"$WORK_MODE\"`.\nOn later setup runs, validate and retain that mode and target unless the owner explicitly changes\nthem. Repository mode: stack detection, Git checks, gates, commits, and verification operate in\nthe work target. Artifact mode: inspection, edits, and verification operate in that folder without\npretending it is a repository.\n\n## 1. Scaffold `$NS/` (never clobber an existing shift)\n\n```bash\n\"$NIGHTSHIFT_PLUGIN_ROOT/runtime/ns\" scaffold\n```\n\nIt writes the files every shift uses that are not already there (the punch list, the parking lot,\nthe snag log, the drafting table and the shift log) and reports `wrote <path>` or `kept <path>`, so\na name the owner already has is left exactly as it is and a second run is a safe repair. Read its\noutput back. The work orders and the product notebook wait until something needs them: Hunt runs\n`ns scaffold work-orders` when it stages an order, and cutting a product-evolution item runs\n`ns scaffold product`. The copies carry resolved absolute paths — a person pasting a command out of\ntheir own punch list has no `$NS` — and the shipped templates are unchanged. Never write those\ntokens into `rules.json`: revival and clock-out text stay owner-editable, and the gate qualifies\nbare `.nightshift/` mentions at injection time.\n\n**State version.** `$NS/state-version` is the schema marker, and it names the layout: this plugin\nwrites version `2`, which groups `$NS/` by purpose. The scaffold writes it into a `$NS/` it creates.\nA site at version `1`, or with no marker (legacy `0`), keeps every state file at the top of `$NS/`\nand goes on working there; offer the move with\n\n```bash\n\"$NIGHTSHIFT_PLUGIN_ROOT/runtime/ns\" migrate-state\n```\n\nwhich only previews: each file with its old and new path, every link it rewrites, every conflict,\nand what it leaves in place. Show that preview, and run it again with `--apply`\nonly after an explicit yes. It refuses while a shift is armed, a watchman is alive or a lock is\nheld, and it never deletes or overwrites. Never move a state file by hand. A marker newer than `2`, or a malformed\nfile, fails closed: print the diagnostic, do not rewrite or downgrade it, and do not continue\nscaffolding as if the site were current.\n\n## 2. Private by default\n\n- Keep run state out of git. If `$NIGHTSHIFT_WORKSPACE` is itself a git repo, append a line\n `.nightshift/` to `$NIGHTSHIFT_WORKSPACE/.gitignore` (create the file if needed; do not\n duplicate the line). If it is not one — the recommended layout, where the code repo sits a\n level below — `.nightshift/` is already outside every repo, so write no `.gitignore` there.\n Run history is the owner's; it never enters the project repo.\n- **Receipts repo — ask, default no.** The run state can be versioned in its own local-only git\n repo inside `$NS/`, so every punch-list change and owner file has history. Most people\n don't want a git repo living inside their project, so ask — *\"version the run state in a local\n receipts repo? (never pushed, never touches your project's history)\"* — and on anything but a\n clear yes, skip it: the receipts still exist as plain files. Present the question neutrally —\n never describe the repo as recommended; the default is no. On yes: if `$NS/.git` does\n not exist, run `git -C \"$NS\" init` rather than `cd`-ing there.\n Ensure `$NS/.gitignore` contains `STOP` and `run/`, the runtime's own folder; preserve existing\n lines. A site still at version `1` keeps the runtime's files at the top of `$NS/`, so there it\n names the transient markers instead: `STOP`, `.stall`, `.notified`, `deadline`, `.session-end`,\n `.shift-pulse`, `.mint-failed`, `.shift-session`, `.shift-session.tmp.*`, `.shift-worker`,\n `.shift-lease`, `.shift-lease.tmp.*`, `.mutex-scope`, `.mutex-scope.tmp.*`, `.watchman`,\n `.watchman-tick`, `.lock.d/`, and `.lease-lock.d/`; migrate-state adds `run/` with the move. Make one initial commit only when setup created the receipts repository.\n Creating the repo does **not** turn on headless auto-commit — that is `receiptsAutoCommit`\n in `rules.json`, shipped `false`; the owner commits the receipts tree when they want.\n **Never add a remote to it, never push it.**\n On native Windows, after a clear yes, rerun the bundled scaffold with the same\n `--work-target` plus `--receipts`; the idempotent pass creates only this local receipts repo.\n- **Cursor CLI file hooks — ask, default no.** The installed Cursor plugin already holds the\n IDE Agent tab. The Cursor CLI (`agent`) currently ignores marketplace and local plugin hooks\n and only runs project file hooks — a Cursor limitation, not a Nightshift skip. Ask —\n *\"write a project `.cursor/hooks.json` so the Cursor CLI is held by the same Nightshift\n hooks?\"* — and on anything but a clear yes, skip it. Present the question neutrally; the\n default is no. The IDE plugin keeps working either way. On yes: if\n `$NIGHTSHIFT_WORKSPACE/.cursor/hooks.json` does not exist, create `.cursor/` if needed and\n copy `$NIGHTSHIFT_PLUGIN_ROOT/hooks/cursor/hooks.json` there. That file execs the same\n plugin scripts via `${CURSOR_PLUGIN_ROOT}`. If a `.cursor/hooks.json` already exists, show\n the diff against the shipped file and write only on an explicit yes to replace; never merge\n unknown owner hooks silently. Never create a second `.nightshift/`.\n\n## 3. Gates — ask, never impose\n\nDetect the stack in the persisted work target from the table in\n`$NIGHTSHIFT_PLUGIN_ROOT/skills/nightshift/references/compose/gates-catalog.md`\n(monorepo-aware). A plugin or marketplace manifest may sit at the work-target\nroot or one directory down at `plugins/<name>/.claude-plugin/` /\n`plugins/<name>/.codex-plugin/`; that nested layout is a match when no\nlanguage-stack row already won. Then ask the\nuser, showing the detected proposal, with three first-class answers:\n\n- **accept** the proposal as-is,\n- **edit** it — add, remove, or replace with THEIR own commands (any shell command is a valid gate),\n- **none** — fully respected: the shift runs without automated checks.\n\nIf gates were accepted or edited, also ask the **site-inspection interval** (every N items or every\nH hours). Write the result into the `## Gates` block of\n`$NS/punch-list.md`, replacing the placeholder. If the answer was none,\nleave the placeholder as-is.\n\nThe `## Gates` block is plain markdown the owner may edit anytime — run Setup again\n(`/nightshift:setup` on Claude Code, or ask Nightshift to set up on Codex) to re-detect after a\nstack change. The contract's immutability binds the agent, not the owner.\n\n**Project defaults — ask once.** Independent from gates. Ask one question covering the verification\nprofile (`fast`, `balanced`, `strict`, or `custom`), typical hours, and tooling policy (existing\ntools only, review missing tools first, or automatically add standard development tools). Persist\nthe answer with\n`\"$NIGHTSHIFT_PLUGIN_ROOT/runtime/ns\" shift-policy defaults-set --verificationProfile <name> --hours <n|null> --toolingPolicy <name> --execution review-first|run-direct`.\nThe helper writes the `shift` block of `$NS/rules.json` — the one file the owner edits — and reports what it stored; never put the answer in\nthe punch list. It only prefills the one question Hunt and Quality ask before composing — it\ndecides nothing on its own, and either skill may change it for a single shift.\n\n- **Artifact** — do not ask. Persist `fast` and existing-tools only, without prompting. A notes\n folder has no repository toolchain to add; repository-tool policies (`auto-add` and\n `review-missing`) are invalid there.\n- **Repository** — ask the full question above (including review-first vs run-direct), then\n persist the answer.\n\n## 4. Permissions — the night cannot click Allow\n\nAn unattended shift stalls forever on a permission prompt, and a watchman revival runs headless —\ndenied means denied. Ask one question:\n\n> Overnight runs can't answer permission prompts. Enable frictionless permissions for this\n> project's unattended runs? (recommended — Nightshift's guards stay armed in every permission\n> mode)\n\n- **Yes, on Claude Code** → merge `{\"permissions\": {\"defaultMode\": \"bypassPermissions\"}}` into\n `$TASK_ROOT/.claude/settings.local.json` (create the file if absent; never clobber keys\n the owner already has). Write the full path: a copy that lands in a nested code repo grants the\n project nothing, and the first prompt of the night proves it. Settings on disk are what revivals\n inherit — a mode picked at launch dies with the process.\n- **Yes, on Codex** → there is no settings file to write: approvals are per launch. Tell the owner\n that unattended execution and sandbox scope are two separate choices, and say the trade plainly:\n a contract that does not commit runs unattended under `-a never -s workspace-write` — ticks alone\n finish a night, in the gate and the stall guard alike, and the commit rule is theirs to strip\n from the punch list and `clockOutMessage`. Under Codex's `workspace-write` sandbox `.git` is\n protected, so the default contract, which commits once per item, cannot run under it and is\n started with the launch command on the Codex host page,\n `$NIGHTSHIFT_PLUGIN_ROOT/skills/nightshift/references/hosts/codex.md`. The fence around that access is nightshift's\n own guards, which hold in every mode — the same trade `bypassPermissions` makes on Claude Code.\n- **No** → respect it and say the cost plainly: *\"a permission prompt mid-shift freezes the night\n until morning — if the shift stalls on one, that was tonight's trade.\"* Suggest the narrower\n alternative: pre-allow just the punch list's tools (test runner, linter, git) in the same file.\n\n## 5. The rules file — every knob in one place\n\nCopy `$NIGHTSHIFT_PLUGIN_ROOT/skills/nightshift/references/nightshift-rules-template.json` to\n`$NS/rules.json` as-is, if it does not already exist — the owner's one config file, defaults\ninline. It lives in nightshift's own folder on purpose: everything nightshift is in one place,\nkept out of repo history by the same `.nightshift/` gitignore, versioned by the receipts repo when\none exists — and deleting `$NS/` removes all of nightshift, rules included. Validate the file with\n`jq -e 'type == \"object\"'` and report a broken one plainly — never half-apply it. On native\nWindows, validate with `Get-Content -Raw -LiteralPath \"$NS\\rules.json\" | ConvertFrom-Json`;\nPowerShell's JSON parser is built in, so native setup has no `jq` or Python prerequisite.\n\nThe template's `$schema` field points at\n`$NIGHTSHIFT_PLUGIN_ROOT/skills/nightshift/references/nightshift-rules.schema.json` so editors\ncatch invalid names, types, and values; it is ignored at runtime. Editor discovery is documented\nin https://github.com/orwa-mahmoud/nightshift/blob/main/docs/knobs.md.\n\nThe rules file is portable across hosts, so never generate a host-specific copy. Its `toolDeny`\nmap carries three native question names: `AskUserQuestion` for Claude Code, `request_user_input`\nfor Codex, and `AskQuestion` for Cursor. A non-empty value denies that exact tool with the owner's\nmessage; an empty value allows it. All three entries stay present so deleting a key can never\nactivate an invisible default. JSON has no comments; the schema descriptions and\nhttps://github.com/orwa-mahmoud/nightshift/blob/main/docs/knobs.md#tool-rules are the inline help.\n\nThe hooks read this file directly on every tool call: an owner's edit applies from their very next\naction. Nothing is synced anywhere, nothing needs a restart, and there is no second copy. Env vars\nof the matching names (`NIGHTSHIFT_FORBIDDEN_COMMANDS`, `NIGHTSHIFT_TOOL_RULES`, …) remain\nsession-start overrides for tests and one-off exceptions — say so only if asked. If Claude Code's\n`$TASK_ROOT/.claude/settings.local.json` still carries `NIGHTSHIFT_*` env keys an earlier version\nsynced from this file, offer to remove them: the file is the one copy.\n\n**Local rule profiles — offer, never impose.** Setup may list the shipped examples in\n`$NIGHTSHIFT_PLUGIN_ROOT/skills/nightshift/references/profiles/` (every version-1 or version-2 JSON\nfile there) and preview one with\n`\"$NIGHTSHIFT_PLUGIN_ROOT/runtime/ns\" apply-profile --profile <name> --mode fill|replace`.\nThe helper prints the preview and the complete next file; read it out rather than describing it.\nApplying requires an explicit yes and `--apply`. Refuse `--apply` while armed. Profiles are a one-time local copy — no network, no\nsubscription. After applying a profile,\nwrite a preset receipt from\n`$NIGHTSHIFT_PLUGIN_ROOT/skills/nightshift/references/receipts/cycle-specialist-evidence.md` so branch mode,\nallowed sources, verification profile, receipt retention, resource limits, and direct-mode\nboundaries trace to `rules.json`. Owner rules remain authoritative;\npresets never capture hidden policy.\n\n**Template evolution — offer, never impose.** On a re-run with the file already present, compare\nthe shipped template's top-level keys and its nested `toolDeny` keys to the owner's file (read the\nJSON in the skill; do not ask the owner to install `jq` or Python; on native Windows,\n`(Get-Content -Raw -LiteralPath \"$NS\\rules.json\" | ConvertFrom-Json).PSObject.Properties.Name`\nand the same for `.toolDeny`): offer any missing key with its default — \"this version added\n`request_user_input`; add it?\" — and never touch a value the owner already has. A missing native\nquestion key is a configuration error, not permission to invent a fallback.\n\nSame posture for the contract: if the shipped punch-list template's contract (the text above\n`## Items`) has changed since the owner's copy was scaffolded, show the diff and offer a merge —\nthe owner's wording wins every conflict, and a punch list with open boxes is never touched at all.\nThe same offer applies when the owner's contract is leftover campaign text (a finished branch,\nrelease, or issue-close list) even if the shipped template has not changed: show the diff and offer\nto restore the template contract, or keep theirs. Never rewrite without an explicit yes.\n\n## 6. Summarize\n\nPrint the workspace-state path and resolved work target, what was scaffolded, whether a receipts\nrepo was created, the gates that were written (or that none were), and the project defaults stored\nin the `shift` block of `$NS/rules.json`. Tell the user to draft items in `$NS/staging/drafting-table.md`, promote them into\nthe punch list, then start the shift (`/nightshift:start` on Claude Code, or ask Nightshift to start\non Codex). Mention that the open-ended product-evolution shift keeps its evidence and ranked work in\n`$NS/product/product-research.md` and `$NS/product/opportunity-map.md`, written the first time such\nan item is cut, while the quality skill can\nturn existing lint/type debt into proposed items whenever they want it.\n"
}

SHA-256 of public snapshot: 845277a3cd0d52d83541b420857ad5ed135acd5b3908804f1ada436a79b74c73