Rename the tutorial to a more generic name

Rather avoid using the name of a popular service
This commit is contained in:
K. Hodges 2026-05-21 03:56:30 -07:00
parent f7fed4535b
commit fb575fc5f7
34 changed files with 112 additions and 112 deletions

View File

@ -124,19 +124,19 @@ Other built-in real-model templates:
```bash ```bash
nightshift init --template real-simple --root bookmarks-demo nightshift init --template real-simple --root bookmarks-demo
nightshift init --template real-long-running --root incident-service nightshift init --template real-long-running --root incident-service
nightshift init --template tutorial-pastebin --root nightshift-pastebin nightshift init --template tutorial-deaddrop --root nightshift-deaddrop
``` ```
Create an isolated integration sandbox for a template: Create an isolated integration sandbox for a template:
```bash ```bash
python -m nightshift.cli integ-run --template tutorial-pastebin python -m nightshift.cli integ-run --template tutorial-deaddrop
``` ```
To create the sandbox and run the Python setup immediately: To create the sandbox and run the Python setup immediately:
```bash ```bash
python -m nightshift.cli integ-run --template tutorial-pastebin --setup python -m nightshift.cli integ-run --template tutorial-deaddrop --setup
``` ```
Then run the Python project setup helper. It finds the generated venv, installs this NightShift checkout into it, installs the target project, installs pytest by default, and runs `nightshift validate`: Then run the Python project setup helper. It finds the generated venv, installs this NightShift checkout into it, installs the target project, installs pytest by default, and runs `nightshift validate`:
@ -387,7 +387,7 @@ Additional docs:
- [Quickstart](QUICKSTART.md) - [Quickstart](QUICKSTART.md)
- [Tutorial 01: imageboard with real local models](examples/tutorial/01-imageboard/README.md) - [Tutorial 01: imageboard with real local models](examples/tutorial/01-imageboard/README.md)
- [Tutorial 02: Lisp with real local models](examples/tutorial/02-lisp/README.md) - [Tutorial 02: Lisp with real local models](examples/tutorial/02-lisp/README.md)
- [Tutorial 03: Pastebin with model fallback and telemetry](examples/tutorial/03-pastebin/README.md) - [Tutorial 03: DeadDrop with fixed tests and telemetry](examples/tutorial/03-deaddrop/README.md)
- [Config reference](docs/config-reference.md) - [Config reference](docs/config-reference.md)
- [Artifact review workflow](docs/artifact-review.md) - [Artifact review workflow](docs/artifact-review.md)
- [Troubleshooting](docs/troubleshooting.md) - [Troubleshooting](docs/troubleshooting.md)

View File

@ -147,13 +147,13 @@ Supported fixture types are `png`, `jpg`, `json`, `sqlite`, `text`, and `blob`.
Create a local integration sandbox from the NightShift repository root: Create a local integration sandbox from the NightShift repository root:
```bash ```bash
python -m nightshift.cli integ-run --template tutorial-pastebin python -m nightshift.cli integ-run --template tutorial-deaddrop
``` ```
Create, set up, validate, and run one task from the generated project directory: Create, set up, validate, and run one task from the generated project directory:
```bash ```bash
python -m nightshift.cli integ-test --template tutorial-pastebin --task TASK-001 python -m nightshift.cli integ-test --template tutorial-deaddrop --task TASK-001
``` ```
Set up the generated Python project: Set up the generated Python project:
@ -185,9 +185,9 @@ python -m nightshift.cli integ-report --latest
To clean up old sandboxes before creating a new one, keep only the newest three existing runs: To clean up old sandboxes before creating a new one, keep only the newest three existing runs:
```bash ```bash
python -m nightshift.cli integ-run --template tutorial-pastebin --keep 3 python -m nightshift.cli integ-run --template tutorial-deaddrop --keep 3
``` ```
## Pastebin Tutorial ## DeadDrop Tutorial
`nightshift init --template tutorial-pastebin` creates a small Flask snippet-hosting target with deterministic tests and incremental NightShift tasks. Its pipeline includes semantic context retrieval, telemetry, debugger support, fixed task-specific tests, and a single default `qwen3-coder:30b` model path. `nightshift init --template tutorial-deaddrop` creates a small Flask snippet sharing utility with deterministic tests and incremental NightShift tasks. Its pipeline includes semantic context retrieval, telemetry, debugger support, fixed task-specific tests, and a single default `qwen3-coder:30b` model path.

View File

@ -344,17 +344,17 @@ because:
```text ```text
PLAN PLAN
↓
REVIEW_PLAN REVIEW_PLAN
↓
IMPLEMENT IMPLEMENT
↓
TEST TEST
↓
STATIC_ANALYSIS STATIC_ANALYSIS
↓
REVIEW REVIEW
↓
DECISION DECISION
``` ```
@ -693,11 +693,11 @@ Validation occurs in multiple stages:
```text ```text
Tests Tests
↓
Static Analysis Static Analysis
↓
Review Agent Review Agent
↓
Decision Decision
``` ```
@ -897,7 +897,7 @@ NightShift currently provides:
* Final task notes, stage summaries, task completion artifacts, and run summaries * Final task notes, stage summaries, task completion artifacts, and run summaries
* Documentation for config, artifact review, troubleshooting, quickstart, and patch workflows * Documentation for config, artifact review, troubleshooting, quickstart, and patch workflows
* A complete fake-agent patch-mode quickstart Lisp example under `examples/quickstart-lisp/` * A complete fake-agent patch-mode quickstart Lisp example under `examples/quickstart-lisp/`
* A deterministic pastebin tutorial template with model fallback configuration * A deterministic DeadDrop tutorial template with fixed-test configuration
The system remains sequential and local-first. It is designed to produce reviewable artifacts and repository state, not to deploy, push, or autonomously ship changes. The system remains sequential and local-first. It is designed to produce reviewable artifacts and repository state, not to deploy, push, or autonomously ship changes.
@ -1181,19 +1181,19 @@ Acceptance Criteria:
- Includes tests for retrieval quality - Includes tests for retrieval quality
- [x] TASK-015: Pastebin tutorial project template - [x] TASK-015: DeadDrop tutorial project template
Dependencies: Dependencies:
- TASK-008 - TASK-008
- TASK-005 - TASK-005
Description: Description:
Add a new tutorial project template for NightShift based on a small Pastebin/snippet-hosting service. This should work like the existing imageboard tutorial, but be simpler, more deterministic, and easier to use for testing agent orchestration. The template should be creatable with `--template`. Add a new tutorial project template for NightShift based on a small DeadDrop snippet sharing utility. This should work like the existing imageboard tutorial, but be simpler, more deterministic, and easier to use for testing agent orchestration. The template should be creatable with `--template`.
Acceptance Criteria: Acceptance Criteria:
- Adds a new template named `pastebin` - Adds a new template named `deaddrop`
- Supports creating the tutorial project with a command such as: - Supports creating the tutorial project with a command such as:
- `nightshift init --template tutorial-pastebin` - `nightshift init --template tutorial-deaddrop`
- Template includes a small but realistic app with: - Template includes a small but realistic app with:
- snippet creation - snippet creation
- snippet viewing - snippet viewing
@ -1206,13 +1206,13 @@ Acceptance Criteria:
- Uses deterministic fixtures and simple dependencies - Uses deterministic fixtures and simple dependencies
- Includes clear task descriptions for the agent to complete - Includes clear task descriptions for the agent to complete
- Includes README instructions explaining the tutorial goals - Includes README instructions explaining the tutorial goals
- Supports model fallback ordering for this template: - Supports single-model fixed-test flow for this template:
- `qwen2.5-coder:14b` - `qwen2.5-coder:14b`
- `carstenuhlig/omnicoder-9b` - `carstenuhlig/omnicoder-9b`
- `deepseek-coder-v2:16b` - `deepseek-coder-v2:16b`
- If the first model fails or exceeds its retry budget, the next fallback model is attempted - If the first model fails or exceeds its retry budget, the next fallback model is attempted
- Records which model handled each attempt - Records which model handled each attempt
- Includes tests for template creation and model fallback configuration - Includes tests for template creation and fixed-test configuration
--- ---
# 17. Current Product Shape # 17. Current Product Shape

View File

@ -12,6 +12,6 @@ Not to implement until we get successful long running runs.
* maybe this is later * maybe this is later
## A way to easily make A/B tests to benchmark models? ## A way to easily make A/B tests to benchmark models?
* Right now I can do this manually, for example I want to run the tutorial-pastebin with qwen3.6:27b as the planner and qwen2.5-coder:14b as the coder, and another with qwen3.6:27b as both, etc. * Right now I can do this manually, for example I want to run the tutorial-deaddrop with qwen3.6:27b as the planner and qwen2.5-coder:14b as the coder, and another with qwen3.6:27b as both, etc.
* Maybe there is a way to make it easier to do that, possibly by creating a template that can be controlled by a larger multi-run file? * Maybe there is a way to make it easier to do that, possibly by creating a template that can be controlled by a larger multi-run file?
* This is probably for way later. * This is probably for way later.

View File

@ -14,7 +14,7 @@ Status: implemented.
Implemented command: Implemented command:
```powershell ```powershell
python -m nightshift.cli integ-test --template tutorial-pastebin --task TASK-001 python -m nightshift.cli integ-test --template tutorial-deaddrop --task TASK-001
``` ```
It creates the integration sandbox, sets up the venv, runs validation through setup, runs the task from the generated project directory, and prints the artifact root. Use `--dry-run` to preview the setup and task command. It creates the integration sandbox, sets up the venv, runs validation through setup, runs the task from the generated project directory, and prints the artifact root. Use `--dry-run` to preview the setup and task command.
@ -24,7 +24,7 @@ Running integration tests is still too manual.
Current process: Current process:
- install the current version of NightShift - install the current version of NightShift
- run `python -m nightshift.cli integ-run --template tutorial-pastebin --setup` - run `python -m nightshift.cli integ-run --template tutorial-deaddrop --setup`
- copy the activation line from the output and run it - copy the activation line from the output and run it
- `cd` into the generated directory - `cd` into the generated directory
- run the task there, because running from the repo root does not find `nightshift.yaml` - run the task there, because running from the repo root does not find `nightshift.yaml`
@ -34,7 +34,7 @@ Recommendation: implement a wrapper command, not just a loose script.
Target command: Target command:
```powershell ```powershell
python -m nightshift.cli integ-test --template tutorial-pastebin --task TASK-001 python -m nightshift.cli integ-test --template tutorial-deaddrop --task TASK-001
``` ```
It should: It should:
@ -49,34 +49,34 @@ It should:
Useful variants: Useful variants:
```powershell ```powershell
python -m nightshift.cli integ-test --template tutorial-pastebin --all python -m nightshift.cli integ-test --template tutorial-deaddrop --all
python -m nightshift.cli integ-test --template tutorial-pastebin --task TASK-002 --keep 3 python -m nightshift.cli integ-test --template tutorial-deaddrop --task TASK-002 --keep 3
``` ```
The base-directory config issue may not be a core bug, but it is bad UX. The wrapper should handle `cwd` correctly. The base-directory config issue may not be a core bug, but it is bad UX. The wrapper should handle `cwd` correctly.
## P0/P1: Remove Multi-Candidate Workflow From Default Pastebin ## P0/P1: Remove Multi-Candidate Workflow From Default DeadDrop
Status: implemented for the default pastebin template and tutorial example. Status: implemented for the default DeadDrop template and tutorial example.
Original idea: Original idea:
- The multi-candidate workflow does not add as much as expected. - The multi-candidate workflow does not add as much as expected.
- Keep it as an example, maybe `example-multiagent`. - Keep it as an example, maybe `example-multiagent`.
Recommendation: yes. Remove it from the default pastebin tutorial. Recommendation: yes. Remove it from the default DeadDrop tutorial.
Reason: Reason:
- Pastebin is becoming the reliability harness. - DeadDrop is becoming the reliability harness.
- Multi-candidate fallback makes artifacts harder to reason about. - Multi-candidate fallback makes artifacts harder to reason about.
- It adds model variability while we are still debugging pipeline behavior. - It adds model variability while we are still debugging pipeline behavior.
Better split: Better split:
```text ```text
tutorial-pastebin tutorial-deaddrop
tutorial-pastebin-multiagent tutorial-deaddrop-multiagent
``` ```
or: or:
@ -85,7 +85,7 @@ or:
examples/templates/multiagent-fallback examples/templates/multiagent-fallback
``` ```
Default pastebin should be boring: Default DeadDrop should be boring:
```text ```text
planner -> semantic_context -> context -> implement -> validate -> test -> review planner -> semantic_context -> context -> implement -> validate -> test -> review
@ -93,9 +93,9 @@ planner -> semantic_context -> context -> implement -> validate -> test -> revie
Use one strong implementer first. Add fallback only in a separate experiment template. Use one strong implementer first. Add fallback only in a separate experiment template.
## P1: Add A Qwen3 / 30B Pastebin Variant ## P1: Add A Qwen3 / 30B DeadDrop Variant
Status: implemented as the default pastebin model path using `qwen3-coder:30b`. Status: implemented as the default DeadDrop model path using `qwen3-coder:30b`.
Original idea: Original idea:
@ -110,7 +110,7 @@ kass reply- No lets make this the default. the qwen3-coder:30b is fast now for m
Suggested template/config: Suggested template/config:
```text ```text
tutorial-pastebin-qwen3 tutorial-deaddrop-qwen3
``` ```
Possible role split: Possible role split:
@ -188,7 +188,7 @@ Original idea:
- Have a test governance layer for when agents write tests. - Have a test governance layer for when agents write tests.
- A reviewer validates alignment with acceptance criteria. - A reviewer validates alignment with acceptance criteria.
Recommendation: yes, but only for generated-test mode. Do not put generated tests back into default pastebin yet. Recommendation: yes, but only for generated-test mode. Do not put generated tests back into default DeadDrop yet.
The previous failures proved test-writing agents will: The previous failures proved test-writing agents will:
@ -240,7 +240,7 @@ Do not modify:
- tests/test_task001.py - tests/test_task001.py
``` ```
This may help smaller models, but it is another model output that can be wrong. Add it only after the fixed-test pipeline works through all pastebin tasks. This may help smaller models, but it is another model output that can be wrong. Add it only after the fixed-test pipeline works through all DeadDrop tasks.
## P2/P3: Add A Test Planner ## P2/P3: Add A Test Planner
@ -267,7 +267,7 @@ test_planner -> write_tests -> test_governance -> implement
For now, fold this idea into the future test governance/analyzer work. For now, fold this idea into the future test governance/analyzer work.
## P1: Add Fixed Tests For All Pastebin Tasks ## P1: Add Fixed Tests For All DeadDrop Tasks
Status: mostly implemented in the template. Status: mostly implemented in the template.

View File

@ -1,6 +1,6 @@
# Tutorial 03: Pastebin With Fixed Tests And Telemetry # Tutorial 03: DeadDrop With Fixed Tests And Telemetry
This tutorial uses the `tutorial-pastebin` template: a small Flask snippet-hosting service designed for deterministic NightShift orchestration tests. This tutorial uses the `tutorial-deaddrop` template: a small Flask snippet sharing utility designed for deterministic NightShift orchestration tests.
It is intentionally simpler than the imageboard tutorial. There are no uploads, thumbnails, sessions, or moderation queues. The work is ordinary web-app behavior: snippet creation, viewing, listing, filtering, expiration handling, and simple HTML forms. It is intentionally simpler than the imageboard tutorial. There are no uploads, thumbnails, sessions, or moderation queues. The work is ordinary web-app behavior: snippet creation, viewing, listing, filtering, expiration handling, and simple HTML forms.
@ -9,26 +9,26 @@ It is intentionally simpler than the imageboard tutorial. There are no uploads,
Run this from a disposable parent directory: Run this from a disposable parent directory:
```bash ```bash
nightshift init --template tutorial-pastebin --root nightshift-pastebin nightshift init --template tutorial-deaddrop --root nightshift-deaddrop
cd nightshift-pastebin cd nightshift-deaddrop
``` ```
For an isolated local integration run, use the integration sandbox command from the NightShift repository root: For an isolated local integration run, use the integration sandbox command from the NightShift repository root:
```bash ```bash
python -m nightshift.cli integ-run --template tutorial-pastebin python -m nightshift.cli integ-run --template tutorial-deaddrop
``` ```
To create, set up, validate, and run one task in a single command: To create, set up, validate, and run one task in a single command:
```bash ```bash
python -m nightshift.cli integ-test --template tutorial-pastebin --task TASK-001 python -m nightshift.cli integ-test --template tutorial-deaddrop --task TASK-001
``` ```
To create the sandbox and set up the Python project immediately: To create the sandbox and set up the Python project immediately:
```bash ```bash
python -m nightshift.cli integ-run --template tutorial-pastebin --setup python -m nightshift.cli integ-run --template tutorial-deaddrop --setup
``` ```
Then set up the generated Python project: Then set up the generated Python project:
@ -56,7 +56,7 @@ nightshift.yaml
reviewer.md reviewer.md
tasks.md tasks.md
src/ src/
pastebin_app/ deaddrop_app/
templates/ templates/
tests/ tests/
pyproject.toml pyproject.toml
@ -79,7 +79,7 @@ Install target dependencies:
python -m pip install -e . pytest flask python -m pip install -e . pytest flask
``` ```
Install and start Ollama, then pull the default pastebin model: Install and start Ollama, then pull the default DeadDrop model:
```bash ```bash
ollama pull qwen3-coder:30b ollama pull qwen3-coder:30b
@ -90,11 +90,11 @@ NightShift uses Ollama's local HTTP API, normally at `http://localhost:11434`.
## Model ## Model
The default pastebin pipeline uses one strong local coder model: The default DeadDrop pipeline uses one strong local coder model:
- `qwen3-coder:30b` - `qwen3-coder:30b`
NightShift records which agent/model handled each stage in `telemetry-summary.md`. Multi-candidate fallback belongs in a separate experiment template, not the default pastebin reliability harness. NightShift records which agent/model handled each stage in `telemetry-summary.md`. Multi-candidate fallback belongs in a separate experiment template, not the default DeadDrop reliability harness.
## TDD Pipeline ## TDD Pipeline
@ -137,4 +137,4 @@ Then inspect:
## Pipeline Reference ## Pipeline Reference
A copy of the template pipeline is included here as [nightshift.yaml](nightshift.yaml). The canonical runnable template lives under `nightshift/project_templates/tutorial-pastebin/`. A copy of the template pipeline is included here as [nightshift.yaml](nightshift.yaml). The canonical runnable template lives under `nightshift/project_templates/tutorial-deaddrop/`.

View File

@ -1,5 +1,5 @@
project: project:
name: pastebin name: deaddrop
root: . root: .
task_file: .nightshift/tasks.md task_file: .nightshift/tasks.md
artifact_dir: .nightshift artifact_dir: .nightshift
@ -20,7 +20,7 @@ safety:
- curl | bash - curl | bash
experiment: experiment:
label: pastebin-qwen3-coder label: deaddrop-qwen3-coder
prompt_variant: fixed-tests-qwen3-coder-30b-v1 prompt_variant: fixed-tests-qwen3-coder-30b-v1
agents: agents:

View File

@ -1,9 +1,9 @@
# Pastebin Tutorial Tasks # DeadDrop Tutorial Tasks
- [ ] TASK-001: Snippet creation and viewing - [ ] TASK-001: Snippet creation and viewing
Description: Description:
Complete the pastebin service foundation. Support creating snippets with title and body. Support viewing a single snippet by id. Complete the snippet sharing utility foundation. Support creating snippets with title and body. Support viewing a single snippet by id.
Acceptance Criteria: Acceptance Criteria:
- POST `/snippets` creates a snippet with title and body - POST `/snippets` creates a snippet with title and body

View File

@ -115,7 +115,7 @@ def build_parser() -> argparse.ArgumentParser:
integ_test_parser.add_argument("--root", default=".", help="Repository root where integ_runs/ is created.") integ_test_parser.add_argument("--root", default=".", help="Repository root where integ_runs/ is created.")
integ_test_parser.add_argument( integ_test_parser.add_argument(
"--template", "--template",
default="tutorial-pastebin", default="tutorial-deaddrop",
choices=available_templates(), choices=available_templates(),
help="Template to initialize inside the sandbox.", help="Template to initialize inside the sandbox.",
) )

View File

@ -23,7 +23,7 @@ class IntegrationTestResult:
def run_integration_test( def run_integration_test(
root: str | Path = ".", root: str | Path = ".",
*, *,
template: str = "tutorial-pastebin", template: str = "tutorial-deaddrop",
task: str | None = None, task: str | None = None,
all_tasks: bool = False, all_tasks: bool = False,
keep: int | None = None, keep: int | None = None,

View File

@ -1,4 +1,4 @@
You are the debugger agent for the NightShift pastebin tutorial. You are the debugger agent for the NightShift DeadDrop tutorial.
Diagnose failed attempts without editing files. Diagnose failed attempts without editing files.
Distinguish fixed-test/template problems from implementation bugs. Distinguish fixed-test/template problems from implementation bugs.

View File

@ -1,11 +1,11 @@
You are the implementation agent for the NightShift pastebin tutorial. You are the implementation agent for the NightShift DeadDrop tutorial.
Implement the smallest application change that satisfies the current task and the generated tests. Implement the smallest application change that satisfies the current task and the generated tests.
Do not rewrite generated tests unless the retry context explicitly says they are inaccurate. Do not rewrite generated tests unless the retry context explicitly says they are inaccurate.
Do not edit files under `tests/`. The tutorial tests are fixed; make the application satisfy them. Do not edit files under `tests/`. The tutorial tests are fixed; make the application satisfy them.
Do not add behavior for future tasks unless needed to satisfy the current tests. Do not add behavior for future tasks unless needed to satisfy the current tests.
Use Flask and `sqlite3` from the Python standard library. Do not use SQLAlchemy, Flask-SQLAlchemy, or undeclared dependencies. Use Flask and `sqlite3` from the Python standard library. Do not use SQLAlchemy, Flask-SQLAlchemy, or undeclared dependencies.
Keep the public package name `pastebin_app`. Keep the public package name `deaddrop_app`.
Keep the public app entry point `create_app(database_path: str | None = None)`. Keep the public app entry point `create_app(database_path: str | None = None)`.
Respect `database_path`; do not hard-code `snippets.db` when a database path is supplied. Respect `database_path`; do not hard-code `snippets.db` when a database path is supplied.
Tests should interact through HTTP routes and `create_app`, not through ORM/session globals. Tests should interact through HTTP routes and `create_app`, not through ORM/session globals.

View File

@ -1,4 +1,4 @@
You are the planning agent for the NightShift pastebin tutorial. You are the planning agent for the NightShift DeadDrop tutorial.
Create a concise TDD implementation plan for the current task. Create a concise TDD implementation plan for the current task.
@ -9,7 +9,7 @@ Plan in this order:
If repository context is needed, request it with lookup_requests. If repository context is needed, request it with lookup_requests.
Prefer small edits and deterministic tests. Prefer small edits and deterministic tests.
Use the actual package and files from repository context. For this tutorial the public app entry point is `pastebin_app.app:create_app`. Use the actual package and files from repository context. For this tutorial the public app entry point is `deaddrop_app.app:create_app`.
Do not assume top-level modules such as `app`, `models`, `routes`, or `main` exist. Do not assume top-level modules such as `app`, `models`, `routes`, or `main` exist.
Do not propose SQLAlchemy, Flask-SQLAlchemy, or ORM globals. Use Flask plus `sqlite3` from the Python standard library. Do not propose SQLAlchemy, Flask-SQLAlchemy, or ORM globals. Use Flask plus `sqlite3` from the Python standard library.
Do not propose tests that import `session`, `Snippet`, `engine`, or other implementation internals. Do not propose tests that import `session`, `Snippet`, `engine`, or other implementation internals.

View File

@ -1,4 +1,4 @@
You are the review agent for the NightShift pastebin tutorial. You are the review agent for the NightShift DeadDrop tutorial.
When reviewing generated tests, check that they map only to the current task acceptance criteria and do not require future-task behavior. When reviewing generated tests, check that they map only to the current task acceptance criteria and do not require future-task behavior.
When reviewing implementation, check that the change is small, deterministic, and satisfies the generated tests without unrelated rewrites. When reviewing implementation, check that the change is small, deterministic, and satisfies the generated tests without unrelated rewrites.

View File

@ -1,4 +1,4 @@
You are the test-writing agent for the NightShift pastebin tutorial. You are the test-writing agent for the NightShift DeadDrop tutorial.
Write only tests for the current task's acceptance criteria. Write only tests for the current task's acceptance criteria.
Do not implement application code. Do not implement application code.
@ -14,8 +14,8 @@ Use one fenced block per file:
Prefer pytest tests that describe the public behavior from the task. Prefer pytest tests that describe the public behavior from the task.
Keep tests deterministic and isolated with temporary databases or temporary paths. Keep tests deterministic and isolated with temporary databases or temporary paths.
Use the existing package name `pastebin_app`. Use the existing package name `deaddrop_app`.
Import only the public app factory: Import only the public app factory:
`from pastebin_app.app import create_app` `from deaddrop_app.app import create_app`
Do not import `app`, `session`, `Snippet`, `engine`, `models`, or top-level modules. Do not import `app`, `session`, `Snippet`, `engine`, `models`, or top-level modules.
Do not use SQLAlchemy or require undeclared dependencies. Do not use SQLAlchemy or require undeclared dependencies.

View File

@ -1,9 +1,9 @@
# Pastebin Tutorial Tasks # DeadDrop Tutorial Tasks
- [ ] TASK-001: Snippet creation and viewing - [ ] TASK-001: Snippet creation and viewing
Description: Description:
Complete the pastebin service foundation. Support creating snippets with title and body. Support viewing a single snippet by id. Complete the snippet sharing utility foundation. Support creating snippets with title and body. Support viewing a single snippet by id.
Acceptance Criteria: Acceptance Criteria:
- POST `/snippets` creates a snippet with title and body - POST `/snippets` creates a snippet with title and body

View File

@ -1,29 +1,29 @@
# NightShift Pastebin Tutorial # NightShift DeadDrop Tutorial
This template is a small deterministic snippet-hosting service for testing NightShift orchestration. This template is a small deterministic snippet sharing utility for testing NightShift orchestration.
Create it with: Create it with:
```bash ```bash
nightshift init --template tutorial-pastebin nightshift init --template tutorial-deaddrop
``` ```
Or create an isolated integration sandbox from the NightShift repository root: Or create an isolated integration sandbox from the NightShift repository root:
```bash ```bash
python -m nightshift.cli integ-run --template tutorial-pastebin python -m nightshift.cli integ-run --template tutorial-deaddrop
``` ```
To create, set up, validate, and run one task in a single command: To create, set up, validate, and run one task in a single command:
```bash ```bash
python -m nightshift.cli integ-test --template tutorial-pastebin --task TASK-001 python -m nightshift.cli integ-test --template tutorial-deaddrop --task TASK-001
``` ```
To create the sandbox and set it up in one step: To create the sandbox and set it up in one step:
```bash ```bash
python -m nightshift.cli integ-run --template tutorial-pastebin --setup python -m nightshift.cli integ-run --template tutorial-deaddrop --setup
``` ```
Then set up the generated Python project: Then set up the generated Python project:
@ -54,7 +54,7 @@ nightshift what-happened
When running from an integration sandbox, the same commands are run inside `integ_runs/<timestamp>/project`. When running from an integration sandbox, the same commands are run inside `integ_runs/<timestamp>/project`.
The default pastebin pipeline uses `qwen3-coder:30b` for planning, implementation, debugging, test review, and final review. It intentionally does not use multi-candidate fallback; pastebin is the deterministic reliability harness. The default DeadDrop pipeline uses `qwen3-coder:30b` for planning, implementation, debugging, test review, and final review. It intentionally does not use multi-candidate fallback; DeadDrop is the deterministic reliability harness.
Telemetry artifacts record which agent/model handled each stage and estimate token usage. Telemetry artifacts record which agent/model handled each stage and estimate token usage.

View File

@ -1,5 +1,5 @@
project: project:
name: pastebin name: deaddrop
root: . root: .
task_file: .nightshift/tasks.md task_file: .nightshift/tasks.md
artifact_dir: .nightshift artifact_dir: .nightshift
@ -20,7 +20,7 @@ safety:
- curl | bash - curl | bash
experiment: experiment:
label: pastebin-qwen3-coder label: deaddrop-qwen3-coder
prompt_variant: fixed-tests-qwen3-coder-30b-v1 prompt_variant: fixed-tests-qwen3-coder-30b-v1
agents: agents:

View File

@ -3,7 +3,7 @@ requires = ["setuptools>=69"]
build-backend = "setuptools.build_meta" build-backend = "setuptools.build_meta"
[project] [project]
name = "nightshift-pastebin-target" name = "nightshift-deaddrop-target"
version = "0.1.0" version = "0.1.0"
requires-python = ">=3.11" requires-python = ">=3.11"
dependencies = ["flask"] dependencies = ["flask"]

View File

@ -0,0 +1 @@
"""DeadDrop package for the NightShift tutorial."""

View File

@ -1,4 +1,4 @@
"""Pastebin tutorial application scaffold.""" """DeadDrop tutorial application scaffold."""
from __future__ import annotations from __future__ import annotations

View File

@ -1,4 +1,4 @@
from pastebin_app.app import create_app from deaddrop_app.app import create_app
def test_create_snippet_returns_created_snippet_id(tmp_path): def test_create_snippet_returns_created_snippet_id(tmp_path):

View File

@ -1,4 +1,4 @@
from pastebin_app.app import create_app from deaddrop_app.app import create_app
def test_create_snippet_accepts_optional_metadata(tmp_path): def test_create_snippet_accepts_optional_metadata(tmp_path):

View File

@ -1,4 +1,4 @@
from pastebin_app.app import create_app from deaddrop_app.app import create_app
def _create(client, title, body, **metadata): def _create(client, title, body, **metadata):

View File

@ -1,4 +1,4 @@
from pastebin_app.app import create_app from deaddrop_app.app import create_app
def test_expired_snippets_are_excluded_from_listing(tmp_path): def test_expired_snippets_are_excluded_from_listing(tmp_path):

View File

@ -1,4 +1,4 @@
from pastebin_app.app import create_app from deaddrop_app.app import create_app
def test_root_shows_snippet_list_html(tmp_path): def test_root_shows_snippet_list_html(tmp_path):

View File

@ -1 +0,0 @@
"""Pastebin package for the NightShift tutorial."""

View File

@ -59,22 +59,22 @@ class InitProjectTests(unittest.TestCase):
self.assertIn("real-long-running", available_templates()) self.assertIn("real-long-running", available_templates())
self.assertIn("real-simple", available_templates()) self.assertIn("real-simple", available_templates())
self.assertIn("tutorial-imageboard", available_templates()) self.assertIn("tutorial-imageboard", available_templates())
self.assertIn("tutorial-pastebin", available_templates()) self.assertIn("tutorial-deaddrop", available_templates())
def test_init_pastebin_template_creates_skeleton_and_qwen3_config(self) -> None: def test_init_DeadDrop_template_creates_skeleton_and_qwen3_config(self) -> None:
with tempfile.TemporaryDirectory() as directory: with tempfile.TemporaryDirectory() as directory:
root = Path(directory) root = Path(directory)
init_project(root, template="tutorial-pastebin") init_project(root, template="tutorial-deaddrop")
config = (root / "nightshift.yaml").read_text(encoding="utf-8") config = (root / "nightshift.yaml").read_text(encoding="utf-8")
self.assertTrue((root / ".nightshift" / "tasks.md").exists()) self.assertTrue((root / ".nightshift" / "tasks.md").exists())
self.assertTrue((root / ".nightshift" / "agents" / "test-writer.md").exists()) self.assertTrue((root / ".nightshift" / "agents" / "test-writer.md").exists())
self.assertTrue((root / "src" / "pastebin_app" / "app.py").exists()) self.assertTrue((root / "src" / "deaddrop_app" / "app.py").exists())
self.assertTrue((root / "tests" / "test_task001.py").exists()) self.assertTrue((root / "tests" / "test_task001.py").exists())
self.assertTrue((root / "tests" / ".gitkeep").exists()) self.assertTrue((root / "tests" / ".gitkeep").exists())
self.assertFalse((root / "tests" / "test_pastebin.py").exists()) self.assertFalse((root / "tests" / "test_deaddrop.py").exists())
self.assertIn("def create_app(database_path", (root / "src" / "pastebin_app" / "app.py").read_text(encoding="utf-8")) self.assertIn("def create_app(database_path", (root / "src" / "deaddrop_app" / "app.py").read_text(encoding="utf-8"))
self.assertIn("type: semantic_context", config) self.assertIn("type: semantic_context", config)
self.assertNotIn("id: write_tests", config) self.assertNotIn("id: write_tests", config)
self.assertNotIn("id: review_tests", config) self.assertNotIn("id: review_tests", config)
@ -88,15 +88,15 @@ class InitProjectTests(unittest.TestCase):
self.assertNotIn("carstenuhlig/omnicoder-9b", config) self.assertNotIn("carstenuhlig/omnicoder-9b", config)
self.assertNotIn("deepseek-coder-v2:16b", config) self.assertNotIn("deepseek-coder-v2:16b", config)
def test_pastebin_example_tutorial_docs_exist(self) -> None: def test_deaddrop_example_tutorial_docs_exist(self) -> None:
root = Path(__file__).resolve().parents[1] root = Path(__file__).resolve().parents[1]
tutorial = root / "examples" / "tutorial" / "03-pastebin" tutorial = root / "examples" / "tutorial" / "03-deaddrop"
self.assertTrue((tutorial / "README.md").exists()) self.assertTrue((tutorial / "README.md").exists())
self.assertTrue((tutorial / "tasks.md").exists()) self.assertTrue((tutorial / "tasks.md").exists())
self.assertTrue((tutorial / "nightshift.yaml").exists()) self.assertTrue((tutorial / "nightshift.yaml").exists())
self.assertIn( self.assertIn(
"nightshift init --template tutorial-pastebin", "nightshift init --template tutorial-deaddrop",
(tutorial / "README.md").read_text(encoding="utf-8"), (tutorial / "README.md").read_text(encoding="utf-8"),
) )

View File

@ -11,7 +11,7 @@ class IntegrationSetupTests(unittest.TestCase):
def test_setup_python_project_dry_run_uses_integration_venv(self) -> None: def test_setup_python_project_dry_run_uses_integration_venv(self) -> None:
with tempfile.TemporaryDirectory() as directory: with tempfile.TemporaryDirectory() as directory:
root = Path(directory) root = Path(directory)
run = create_integration_run(root, template="tutorial-pastebin") run = create_integration_run(root, template="tutorial-deaddrop")
result = setup_python_project( result = setup_python_project(
run.directory / "project", run.directory / "project",
@ -48,7 +48,7 @@ class IntegrationSetupTests(unittest.TestCase):
def test_format_setup_result_includes_activation_hint(self) -> None: def test_format_setup_result_includes_activation_hint(self) -> None:
with tempfile.TemporaryDirectory() as directory: with tempfile.TemporaryDirectory() as directory:
root = Path(directory) root = Path(directory)
run = create_integration_run(root, template="tutorial-pastebin") run = create_integration_run(root, template="tutorial-deaddrop")
result = setup_python_project( result = setup_python_project(
run.directory / "project", run.directory / "project",

View File

@ -11,7 +11,7 @@ class IntegrationTestCommandTests(unittest.TestCase):
with tempfile.TemporaryDirectory() as directory: with tempfile.TemporaryDirectory() as directory:
result = run_integration_test( result = run_integration_test(
directory, directory,
template="tutorial-pastebin", template="tutorial-deaddrop",
task="TASK-001", task="TASK-001",
dry_run=True, dry_run=True,
) )

View File

@ -30,14 +30,14 @@ class ReliabilityFeatureTests(unittest.TestCase):
"\n".join( "\n".join(
[ [
"ImportError while importing test module 'tests/test_app.py'.", "ImportError while importing test module 'tests/test_app.py'.",
"ModuleNotFoundError: No module named 'pastebin_app'", "ModuleNotFoundError: No module named 'deaddrop_app'",
] ]
), ),
exit_code=2, exit_code=2,
) )
self.assertEqual(result.category, "missing dependency") self.assertEqual(result.category, "missing dependency")
self.assertIn("pastebin_app", result.probable_root_cause) self.assertIn("deaddrop_app", result.probable_root_cause)
def test_failure_classifier_detects_local_import_mismatch(self) -> None: def test_failure_classifier_detects_local_import_mismatch(self) -> None:
result = classify_failure( result = classify_failure(
@ -75,7 +75,7 @@ class ReliabilityFeatureTests(unittest.TestCase):
result = classify_failure( result = classify_failure(
"\n".join( "\n".join(
[ [
' File "C:\\repo\\project\\src\\pastebin_app\\app.py", line 31, in get_db', ' File "C:\\repo\\project\\src\\deaddrop_app\\app.py", line 31, in get_db',
" if 'db' not in g:", " if 'db' not in g:",
"NameError: name 'g' is not defined", "NameError: name 'g' is not defined",
] ]
@ -84,7 +84,7 @@ class ReliabilityFeatureTests(unittest.TestCase):
) )
self.assertEqual(result.category, "logic bug") self.assertEqual(result.category, "logic bug")
self.assertIn("src\\pastebin_app\\app.py", result.probable_root_cause) self.assertIn("src\\deaddrop_app\\app.py", result.probable_root_cause)
def test_retry_churn_stops_on_repeated_failure_signature(self) -> None: def test_retry_churn_stops_on_repeated_failure_signature(self) -> None:
entries = ( entries = (
@ -94,7 +94,7 @@ class ReliabilityFeatureTests(unittest.TestCase):
status="fail", status="fail",
cause="Command exited with code 1: python -m pytest -q", cause="Command exited with code 1: python -m pytest -q",
next_stage="implement", next_stage="implement",
failure_signature="NameError | src/pastebin_app/app.py | 31 | python -m pytest -q", failure_signature="NameError | src/deaddrop_app/app.py | 31 | python -m pytest -q",
), ),
RetryMemoryEntry( RetryMemoryEntry(
attempt=2, attempt=2,
@ -102,7 +102,7 @@ class ReliabilityFeatureTests(unittest.TestCase):
status="fail", status="fail",
cause="Command exited with code 1: python -m pytest -q", cause="Command exited with code 1: python -m pytest -q",
next_stage="implement", next_stage="implement",
failure_signature="NameError | src/pastebin_app/app.py | 31 | python -m pytest -q", failure_signature="NameError | src/deaddrop_app/app.py | 31 | python -m pytest -q",
), ),
) )
@ -119,7 +119,7 @@ class ReliabilityFeatureTests(unittest.TestCase):
status="fail", status="fail",
cause="Command exited with code 1: python -m pytest -q", cause="Command exited with code 1: python -m pytest -q",
next_stage="implement", next_stage="implement",
failure_signature="NameError | src/pastebin_app/app.py | 31 | python -m pytest -q", failure_signature="NameError | src/deaddrop_app/app.py | 31 | python -m pytest -q",
) )
for attempt in range(1, 4) for attempt in range(1, 4)
) )
@ -132,7 +132,7 @@ class ReliabilityFeatureTests(unittest.TestCase):
signature = build_failure_signature( signature = build_failure_signature(
"\n".join( "\n".join(
[ [
' File "C:\\repo\\project\\src\\pastebin_app\\app.py", line 31, in get_db', ' File "C:\\repo\\project\\src\\deaddrop_app\\app.py", line 31, in get_db',
"NameError: name 'g' is not defined", "NameError: name 'g' is not defined",
' File "C:\\Users\\metis\\...\\site-packages\\_pytest\\cacheprovider.py", line 429, in set', ' File "C:\\Users\\metis\\...\\site-packages\\_pytest\\cacheprovider.py", line 429, in set',
] ]
@ -140,7 +140,7 @@ class ReliabilityFeatureTests(unittest.TestCase):
reason="Command exited with code 1: python -m pytest -q", reason="Command exited with code 1: python -m pytest -q",
) )
self.assertIn("src\\pastebin_app\\app.py", signature) self.assertIn("src\\deaddrop_app\\app.py", signature)
self.assertNotIn("_pytest\\cacheprovider.py", signature) self.assertNotIn("_pytest\\cacheprovider.py", signature)
def test_command_failure_writes_diagnostics_and_retry_memory(self) -> None: def test_command_failure_writes_diagnostics_and_retry_memory(self) -> None:

View File

@ -32,7 +32,7 @@ class WhatHappenedTests(unittest.TestCase):
encoding="utf-8", encoding="utf-8",
) )
(task_dir / "test-output-1.txt").write_text( (task_dir / "test-output-1.txt").write_text(
"Command: `python -m pytest -q`\nExit code: 2\nModuleNotFoundError: No module named 'pastebin_app'\n", "Command: `python -m pytest -q`\nExit code: 2\nModuleNotFoundError: No module named 'deaddrop_app'\n",
encoding="utf-8", encoding="utf-8",
) )
(diagnostics / "test-failure-retry-1.md").write_text( (diagnostics / "test-failure-retry-1.md").write_text(