mirror of
https://github.com/khodges42/nightShift.git
synced 2026-06-14 10:08:37 +00:00
close out phase2 and support quickstart
This commit is contained in:
parent
4e502ba494
commit
a8616a1062
|
|
@ -1,6 +1,6 @@
|
|||
# NightShift Quickstart
|
||||
|
||||
This guide runs the current MVP with safe example files.
|
||||
This guide runs NightShift with safe example files, including an end-to-end patch workflow.
|
||||
|
||||
## 1. Install for Development
|
||||
|
||||
|
|
@ -67,9 +67,16 @@ Useful files:
|
|||
```text
|
||||
run-summary.md
|
||||
config.snapshot.yaml
|
||||
project-context-chart.md
|
||||
tasks/TASK-001/task.md
|
||||
tasks/TASK-001/context.md
|
||||
tasks/TASK-001/plan.md
|
||||
tasks/TASK-001/context-pack.md
|
||||
tasks/TASK-001/proposed.patch
|
||||
tasks/TASK-001/normalized.patch
|
||||
tasks/TASK-001/patch-validation.md
|
||||
tasks/TASK-001/applied.patch
|
||||
tasks/TASK-001/patch-apply-output.txt
|
||||
tasks/TASK-001/test-output.txt
|
||||
tasks/TASK-001/stage-results.md
|
||||
tasks/TASK-001/context-out.md
|
||||
|
|
@ -87,7 +94,7 @@ The repository also includes a complete sample target project:
|
|||
examples/quickstart-lisp/
|
||||
```
|
||||
|
||||
Copy that directory elsewhere if you want to test NightShift against a multi-task project.
|
||||
Copy that directory elsewhere if you want to test NightShift against a multi-task project that modifies real code through patch mode.
|
||||
|
||||
## Quickstart Test Project
|
||||
|
||||
|
|
@ -127,12 +134,12 @@ safety:
|
|||
agents:
|
||||
planner:
|
||||
backend: command
|
||||
command: echo
|
||||
command: python agents/fake_planner.py
|
||||
system_prompt: agents/planner.md
|
||||
|
||||
implementer:
|
||||
backend: command
|
||||
command: echo
|
||||
command: python agents/fake_code_writer.py
|
||||
system_prompt: agents/implementer.md
|
||||
|
||||
reviewer:
|
||||
|
|
@ -149,16 +156,34 @@ pipeline:
|
|||
agent: planner
|
||||
output: plan.md
|
||||
|
||||
- id: context
|
||||
type: repo_context
|
||||
output: context-pack.md
|
||||
|
||||
- id: implement
|
||||
type: agent
|
||||
type: code_writer
|
||||
agent: implementer
|
||||
output: implementation-log.md
|
||||
output: proposed.patch
|
||||
|
||||
- id: normalize
|
||||
type: patch_normalizer
|
||||
output: normalized.patch
|
||||
|
||||
- id: validate_patch
|
||||
type: patch_validator
|
||||
output: patch-validation.md
|
||||
|
||||
- id: apply_patch
|
||||
type: patch_apply
|
||||
mode: apply
|
||||
output: patch-apply-output.txt
|
||||
|
||||
- id: test
|
||||
type: command
|
||||
commands:
|
||||
- python -m unittest discover -v
|
||||
output: test-output.txt
|
||||
on_fail: implement
|
||||
|
||||
- id: review
|
||||
type: agent_review
|
||||
|
|
@ -171,7 +196,7 @@ pipeline:
|
|||
output: final-notes.md
|
||||
```
|
||||
|
||||
This uses fake command agents so the pipeline is safe and deterministic. Replace `command: echo` later with your real local agent wrapper.
|
||||
This uses fake command-backed planner and code-writer fixtures so the pipeline is deterministic but still inspects files and modifies real files through patch mode. Replace the fake agent commands later with your real local agent wrapper.
|
||||
|
||||
### 3. Add `tasks.md`
|
||||
|
||||
|
|
@ -242,10 +267,12 @@ Do not write code. Include files to edit, tests to add, and risks.
|
|||
`agents/implementer.md`:
|
||||
|
||||
```markdown
|
||||
You are the implementation agent. Implement the smallest correct change.
|
||||
Preserve existing behavior and include tests.
|
||||
You are the implementation agent. Output only a unified diff.
|
||||
Preserve existing behavior and include tests when needed.
|
||||
```
|
||||
|
||||
For deterministic local fixtures, add `agents/fake_planner.py` that requests file lookups and `agents/fake_code_writer.py` that prints a unified diff. The included `examples/quickstart-lisp/` project contains working fixtures.
|
||||
|
||||
`agents/reviewer.md`:
|
||||
|
||||
```markdown
|
||||
|
|
@ -288,7 +315,9 @@ Run all currently runnable tasks:
|
|||
nightshift run --all
|
||||
```
|
||||
|
||||
Because the example uses fake agents, it will not actually implement the Lisp interpreter by itself. It is meant to verify the pipeline, dependency handling, reports, and artifacts before you connect a real command-backed agent.
|
||||
The included `examples/quickstart-lisp/` fake code writer implements the first parser task by emitting a patch. It exercises lookup, context-pack generation, patch normalization, validation, application, tests, reports, and artifacts before you connect a real model-backed agent.
|
||||
|
||||
Use `mode: dry_run` on the `patch_apply` stage when you want to verify that a patch would apply without changing files. Use `mode: apply` when the validated patch should be written to the target project.
|
||||
|
||||
### 7. Review Artifacts
|
||||
|
||||
|
|
@ -297,10 +326,16 @@ After a run, inspect:
|
|||
```text
|
||||
.nightshift/runs/<run-id>/run-summary.md
|
||||
.nightshift/runs/<run-id>/tasks/TASK-001/plan.md
|
||||
.nightshift/runs/<run-id>/tasks/TASK-001/implementation-log.md
|
||||
.nightshift/runs/<run-id>/tasks/TASK-001/files-inspected.md
|
||||
.nightshift/runs/<run-id>/tasks/TASK-001/context-pack.md
|
||||
.nightshift/runs/<run-id>/tasks/TASK-001/proposed.patch
|
||||
.nightshift/runs/<run-id>/tasks/TASK-001/normalized.patch
|
||||
.nightshift/runs/<run-id>/tasks/TASK-001/patch-validation.md
|
||||
.nightshift/runs/<run-id>/tasks/TASK-001/applied.patch
|
||||
.nightshift/runs/<run-id>/tasks/TASK-001/patch-apply-output.txt
|
||||
.nightshift/runs/<run-id>/tasks/TASK-001/test-output.txt
|
||||
.nightshift/runs/<run-id>/tasks/TASK-001/review.md
|
||||
.nightshift/runs/<run-id>/tasks/TASK-001/final-notes.md
|
||||
```
|
||||
|
||||
The useful signal is whether NightShift selected the right task, respected dependencies, ran the command stage, wrote artifacts, updated task completion, and produced a clear summary.
|
||||
The useful signal is whether NightShift selected the right task, respected dependencies, generated context, validated and applied a patch, ran tests, wrote artifacts, updated task completion, and produced a clear summary.
|
||||
|
|
|
|||
|
|
@ -1086,27 +1086,27 @@ Notes:
|
|||
|
||||
## Phase 32: Patch Apply / Dry Run
|
||||
|
||||
- [ ] Add `patch_apply` stage.
|
||||
- [ ] Support `mode: dry_run`.
|
||||
- [ ] Support `mode: apply`.
|
||||
- [ ] Save `applied.patch`.
|
||||
- [ ] Preserve pre/post git status.
|
||||
- [ ] Fail cleanly on apply errors.
|
||||
- [x] Add `patch_apply` stage.
|
||||
- [x] Support `mode: dry_run`.
|
||||
- [x] Support `mode: apply`.
|
||||
- [x] Save `applied.patch`.
|
||||
- [x] Preserve pre/post git status.
|
||||
- [x] Fail cleanly on apply errors.
|
||||
|
||||
## Phase 33: Test Feedback Repair Loop
|
||||
|
||||
- [ ] Feed test/static failure output back into implementer.
|
||||
- [ ] Add bounded repair attempts.
|
||||
- [ ] Save each repair patch.
|
||||
- [ ] Save repair summaries.
|
||||
- [ ] Stop after max retry count.
|
||||
- [x] Feed test/static failure output back into implementer.
|
||||
- [x] Add bounded repair attempts.
|
||||
- [x] Save each repair patch.
|
||||
- [x] Save repair summaries.
|
||||
- [x] Stop after max retry count.
|
||||
|
||||
## Phase 34: End-to-End Coding Quickstart
|
||||
|
||||
- [ ] Update quickstart to modify real code.
|
||||
- [ ] Include fake-agent test fixture.
|
||||
- [ ] Demonstrate lookup → context pack → patch → apply → test.
|
||||
- [ ] Document dry-run vs apply mode.
|
||||
- [x] Update quickstart to modify real code.
|
||||
- [x] Include fake-agent test fixture.
|
||||
- [x] Demonstrate lookup → context pack → patch → apply → test.
|
||||
- [x] Document dry-run vs apply mode.
|
||||
---
|
||||
|
||||
# Appendix A: Design Decisions and Rationale
|
||||
|
|
|
|||
20
examples/quickstart-lisp/agents/fake_planner.py
Normal file
20
examples/quickstart-lisp/agents/fake_planner.py
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
"""Fake planner for the NightShift end-to-end quickstart."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
prompt = sys.stdin.read()
|
||||
if "repo_lookup_results" in prompt:
|
||||
print("# Plan")
|
||||
print("")
|
||||
print("- Use the context pack and inspected files.")
|
||||
print("- Add parser functions to `lisp.py`.")
|
||||
print("- Replace the smoke test with parser unit tests.")
|
||||
else:
|
||||
print("lookup_requests:")
|
||||
print("- tool: read_file")
|
||||
print(" path: lisp.py")
|
||||
print("- tool: read_file")
|
||||
print(" path: tests/test_lisp.py")
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
You are the implementation agent.
|
||||
|
||||
Implement the smallest correct change and include tests.
|
||||
Output only a unified diff.
|
||||
Implement the smallest correct change and include tests when needed.
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ experiment:
|
|||
agents:
|
||||
planner:
|
||||
backend: command
|
||||
command: echo
|
||||
command: python agents/fake_planner.py
|
||||
system_prompt: agents/planner.md
|
||||
|
||||
implementer:
|
||||
|
|
@ -44,6 +44,10 @@ pipeline:
|
|||
agent: planner
|
||||
output: plan.md
|
||||
|
||||
- id: context
|
||||
type: repo_context
|
||||
output: context-pack.md
|
||||
|
||||
- id: implement
|
||||
type: code_writer
|
||||
agent: implementer
|
||||
|
|
|
|||
|
|
@ -103,9 +103,9 @@ def format_validation_result(result: PatchValidationResult) -> str:
|
|||
|
||||
def apply_patch_with_git(patch_path: Path, project_root: str | Path, mode: str = "dry_run") -> PatchApplyResult:
|
||||
root = resolve_project_root(project_root)
|
||||
command = ["git", "apply", "--check", str(patch_path)]
|
||||
command = ["git", "apply", "--ignore-whitespace", "--check", str(patch_path)]
|
||||
if mode == "apply":
|
||||
command = ["git", "apply", str(patch_path)]
|
||||
command = ["git", "apply", "--ignore-whitespace", str(patch_path)]
|
||||
completed = subprocess.run(
|
||||
command,
|
||||
cwd=root,
|
||||
|
|
|
|||
|
|
@ -155,6 +155,8 @@ class PipelineRunner:
|
|||
reason=f"Unexpected OS error while running stage: {exc}",
|
||||
)
|
||||
stage_results.append(result)
|
||||
if stage.id in previous_outputs:
|
||||
del previous_outputs[stage.id]
|
||||
previous_outputs[stage.id] = self._read_output(result.output_path)
|
||||
self.logger.event(
|
||||
"stage.finish",
|
||||
|
|
|
|||
|
|
@ -469,6 +469,7 @@ Acceptance Criteria:
|
|||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
test_command = 'python -c "from pathlib import Path; raise SystemExit(0 if Path(\'app.py\').read_text().strip() == \'new\' else 1)"'
|
||||
stages = (
|
||||
StageConfig(id="write", type="code_writer", agent="writer"),
|
||||
StageConfig(id="normalize", type="patch_normalizer"),
|
||||
|
|
@ -477,7 +478,7 @@ Acceptance Criteria:
|
|||
StageConfig(
|
||||
id="test",
|
||||
type="command",
|
||||
commands=('python -c "from pathlib import Path; raise SystemExit(0 if Path(\'app.py\').read_text() == \'new\\\\n\' else 1)"',),
|
||||
commands=(test_command,),
|
||||
output="test-output.txt",
|
||||
on_fail="write",
|
||||
),
|
||||
|
|
@ -490,10 +491,10 @@ Acceptance Criteria:
|
|||
config = replace(
|
||||
config,
|
||||
safety=SafetyConfig(
|
||||
require_clean_worktree=False,
|
||||
scoped_paths=(".",),
|
||||
allowed_commands=('python -c "from pathlib import Path; raise SystemExit(0 if Path(\'app.py\').read_text() == \'new\\\\n\' else 1)"',),
|
||||
forbidden_commands=("rm -rf",),
|
||||
require_clean_worktree=False,
|
||||
scoped_paths=(".",),
|
||||
allowed_commands=(test_command,),
|
||||
forbidden_commands=("rm -rf",),
|
||||
),
|
||||
)
|
||||
config.agents["writer"] = AgentConfig(
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user