nubos-pilot 0.9.2 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agents/np-build-fixer.md +4 -1
- package/agents/np-critic-acceptance.md +1 -0
- package/agents/np-executor.md +3 -0
- package/bin/np-tools/config.cjs +4 -4
- package/bin/np-tools/config.test.cjs +61 -0
- package/lib/config-defaults.cjs +12 -0
- package/package.json +1 -1
- package/workflows/execute-phase.md +2 -0
package/agents/np-build-fixer.md
CHANGED
|
@@ -90,7 +90,7 @@ node .nubos-pilot/bin/np-tools.cjs handoff-write \
|
|
|
90
90
|
- **Success:** verify command exits 0; no extra files written; control returned to executor.
|
|
91
91
|
- **Stuck after 3 attempts:** write `T<NNNN>-FIX-NOTES.md` next to the task plan; emit `## FIX FAILED` block listing attempts + suspected cause.
|
|
92
92
|
- **Out-of-scope failure:** emit `## SCOPE EXPANSION REQUEST` block listing the out-of-scope path + the symbol involved; do NOT edit.
|
|
93
|
-
- **
|
|
93
|
+
- **Infrastructure mismatch (container down, wrong runtime version, missing service):** this is NOT a fix-target. Emit a finding tagged `information-missing` with the specific mismatch (e.g., `composer requires php ^8.5, container runs 8.4`) so `loop-evaluate` routes to the researcher swarm or plan-checker, not back to you. Do NOT edit Dockerfiles, compose configs, or other infra paths to "make verify green" — that's outside any task's `files_modified`.
|
|
94
94
|
|
|
95
95
|
<scope_guardrail>
|
|
96
96
|
**Do:**
|
|
@@ -98,6 +98,7 @@ node .nubos-pilot/bin/np-tools.cjs handoff-write \
|
|
|
98
98
|
- Run the task's verify command via Bash.
|
|
99
99
|
- Use `knowledge-search` for unfamiliar symbols.
|
|
100
100
|
- Stop after 3 failed attempts and document.
|
|
101
|
+
- Distinguish code failures (your job) from infrastructure failures (route via finding).
|
|
101
102
|
|
|
102
103
|
**Don't:**
|
|
103
104
|
- Expand `files_modified` — that's the planner's job; emit a SCOPE EXPANSION REQUEST instead.
|
|
@@ -106,4 +107,6 @@ node .nubos-pilot/bin/np-tools.cjs handoff-write \
|
|
|
106
107
|
- Silence failures with empty catches, skipped tests, or commented-out assertions.
|
|
107
108
|
- Re-litigate locked decisions in `M<NNN>-CONTEXT.md` or `RULES.md`.
|
|
108
109
|
- Spawn other agents.
|
|
110
|
+
- Edit infrastructure (Dockerfile, docker-compose, k8s, CI configs) to fix verify-red — those paths are out of scope for any task; surface the mismatch as an `information-missing` finding instead.
|
|
111
|
+
- Treat container-down / runtime-version-skew as a code bug. It's an environment routing signal, not a code-fixable failure.
|
|
109
112
|
</scope_guardrail>
|
|
@@ -48,6 +48,7 @@ The orchestrator provides these paths in your prompt context. Read every path it
|
|
|
48
48
|
2. **Locked-decision conformance** — the diff does not violate any locked decision in `M<NNN>-CONTEXT.md`. Violations are findings of category `locked-decision-violation`.
|
|
49
49
|
3. **Scope creep** — the diff does not edit files outside `files_modified`. Out-of-scope edits are findings of category `scope-creep`.
|
|
50
50
|
4. **Stuck-marker check** — if the task is on round 3 with no progress between rounds, you flag `stuck-detected` so the orchestrator escalates.
|
|
51
|
+
5. **Infrastructure-mismatch detection** — if the verify output indicates an infrastructure failure (container exited, runtime version skew, missing service: `php -v` mismatch, `docker exec` errors, port-not-bound, DB-unreachable), do NOT downgrade affected criteria to `Unsatisfied` or `Satisfied`. Mark them `Information-Missing` with a finding of category `information-missing` whose `remediation` names the specific environment delta (e.g., `composer requires php ^8.5, container runs 8.4 — Dockerfile bump required outside this milestone`). The orchestrator routes that to researcher / plan-checker, not back to executor — the code is not at fault.
|
|
51
52
|
|
|
52
53
|
## Output Schema
|
|
53
54
|
|
package/agents/np-executor.md
CHANGED
|
@@ -117,6 +117,7 @@ into the `task(…)` commit. If `workflow.commit_docs=true`, the
|
|
|
117
117
|
- Commit via `node np-tools.cjs commit-task <task-id>`.
|
|
118
118
|
- Write checkpoint state transitions via the wrapper.
|
|
119
119
|
- Stay within the task's declared scope even if you spot tangential issues — log them, do not fix them.
|
|
120
|
+
- Run the task's `<verify>` command and capture its exit code + output. If it fails because the runtime environment is wrong (container exited, wrong PHP/Node version, missing service), surface that in the verify output verbatim — the Nubosloop's `loop-run-round --phase post-executor` reads the exit code and routes accordingly. The infra issue is a routing signal, not your decision.
|
|
120
121
|
|
|
121
122
|
**Don't:**
|
|
122
123
|
- Add files to the commit beyond `files_modified` (D-04 authoritative).
|
|
@@ -124,6 +125,8 @@ into the `task(…)` commit. If `workflow.commit_docs=true`, the
|
|
|
124
125
|
- Bypass the checkpoint wrapper.
|
|
125
126
|
- Use `--no-verify`, `--force`, `git reset --hard`, `git clean`, `git restore .`, or any destructive git flag.
|
|
126
127
|
- Auto-discover files via `git status` — the plan declares scope, not the filesystem.
|
|
128
|
+
- **Pre-validate the runtime environment** (`docker ps`, `php -v`, `node -v`, container-status checks, DB connectivity probes). The orchestrator's pre-flight phase covers what needs to be checked; you do code edits and run verify. If the container is down or the runtime is wrong, the verify command will fail and the loop routes that — never declare a "hard blocker" or abort the spawn over environment state.
|
|
129
|
+
- **Refuse to spawn / halt before editing because of infra mismatch** (PHP version skew, missing image, etc.). Tasks edit code, not infrastructure. Run your edits, run verify, let the result speak.
|
|
127
130
|
</scope_guardrail>
|
|
128
131
|
|
|
129
132
|
## Handoff Protocol
|
package/bin/np-tools/config.cjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const fs = require('node:fs');
|
|
2
2
|
const path = require('node:path');
|
|
3
3
|
const { findProjectRoot, NubosPilotError } = require('../../lib/core.cjs');
|
|
4
|
+
const { DEFAULT_CONFIG_TREE } = require('../../lib/config-defaults.cjs');
|
|
4
5
|
|
|
5
6
|
const SEGMENT_RE = /^[a-zA-Z0-9_-]+$/;
|
|
6
7
|
const BLOCKED_SEGMENTS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
@@ -75,11 +76,10 @@ function run(argv, ctx) {
|
|
|
75
76
|
try {
|
|
76
77
|
_validateSegments(segments);
|
|
77
78
|
const config = _readConfig(cwd);
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
let value = config == null ? undefined : _walkPath(config, segments);
|
|
80
|
+
if (value === undefined) {
|
|
81
|
+
value = _walkPath(DEFAULT_CONFIG_TREE, segments);
|
|
81
82
|
}
|
|
82
|
-
const value = _walkPath(config, segments);
|
|
83
83
|
if (value === undefined) {
|
|
84
84
|
if (!raw) stdout.write('\n');
|
|
85
85
|
return 0;
|
|
@@ -69,3 +69,64 @@ test('CONFIG-4: object value serialized as JSON', () => {
|
|
|
69
69
|
assert.equal(code, 0);
|
|
70
70
|
assert.equal(stdout.toString(), '{"k":"v"}');
|
|
71
71
|
});
|
|
72
|
+
|
|
73
|
+
test('CONFIG-5: returns DEFAULT_CONFIG_TREE value when key absent from user config', () => {
|
|
74
|
+
const sb = makeSandbox({ runtime: 'claude' });
|
|
75
|
+
const stdout = makeSink();
|
|
76
|
+
const code = configCli.run(['loop.maxRounds'], { cwd: sb, stdout, stderr: makeSink() });
|
|
77
|
+
assert.equal(code, 0);
|
|
78
|
+
assert.equal(stdout.toString(), '3\n');
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test('CONFIG-6: defaults walk into nested swarm.research.* keys', () => {
|
|
82
|
+
const sb = makeSandbox({});
|
|
83
|
+
const out1 = makeSink(); configCli.run(['swarm.research.k'], { cwd: sb, stdout: out1, stderr: makeSink() });
|
|
84
|
+
const out2 = makeSink(); configCli.run(['swarm.research.threshold'], { cwd: sb, stdout: out2, stderr: makeSink() });
|
|
85
|
+
const out3 = makeSink(); configCli.run(['swarm.research.minOccurrence'], { cwd: sb, stdout: out3, stderr: makeSink() });
|
|
86
|
+
assert.equal(out1.toString(), '3\n');
|
|
87
|
+
assert.equal(out2.toString(), '0.9\n');
|
|
88
|
+
assert.equal(out3.toString(), '3\n');
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test('CONFIG-7: user-set value wins over default', () => {
|
|
92
|
+
const sb = makeSandbox({ loop: { maxRounds: 5 } });
|
|
93
|
+
const stdout = makeSink();
|
|
94
|
+
configCli.run(['loop.maxRounds'], { cwd: sb, stdout, stderr: makeSink() });
|
|
95
|
+
assert.equal(stdout.toString(), '5\n');
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
test('CONFIG-8: partial user override falls through to defaults for sibling keys', () => {
|
|
99
|
+
const sb = makeSandbox({ swarm: { research: { k: 7 } } });
|
|
100
|
+
const k = makeSink(); configCli.run(['swarm.research.k'], { cwd: sb, stdout: k, stderr: makeSink() });
|
|
101
|
+
const t = makeSink(); configCli.run(['swarm.research.threshold'], { cwd: sb, stdout: t, stderr: makeSink() });
|
|
102
|
+
assert.equal(k.toString(), '7\n');
|
|
103
|
+
assert.equal(t.toString(), '0.9\n');
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
test('CONFIG-9: unknown key without a default still returns empty', () => {
|
|
107
|
+
const sb = makeSandbox({});
|
|
108
|
+
const stdout = makeSink();
|
|
109
|
+
configCli.run(['really.not.a.thing'], { cwd: sb, stdout, stderr: makeSink() });
|
|
110
|
+
assert.equal(stdout.toString(), '\n');
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test('CONFIG-10: defaults resolve even without config.json present', () => {
|
|
114
|
+
const sb = makeSandbox(); // no config.json
|
|
115
|
+
const stdout = makeSink();
|
|
116
|
+
configCli.run(['loop.maxRounds'], { cwd: sb, stdout, stderr: makeSink() });
|
|
117
|
+
assert.equal(stdout.toString(), '3\n');
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test('CONFIG-11: explicit user false wins over default true (boolean handling)', () => {
|
|
121
|
+
const sb = makeSandbox({ auto_log_learning: false });
|
|
122
|
+
const stdout = makeSink();
|
|
123
|
+
configCli.run(['auto_log_learning'], { cwd: sb, stdout, stderr: makeSink() });
|
|
124
|
+
assert.equal(stdout.toString(), 'false\n');
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
test('CONFIG-12: --raw mode resolves defaults without trailing newline', () => {
|
|
128
|
+
const sb = makeSandbox({});
|
|
129
|
+
const stdout = makeSink();
|
|
130
|
+
configCli.run(['loop.maxRounds', '--raw'], { cwd: sb, stdout, stderr: makeSink() });
|
|
131
|
+
assert.equal(stdout.toString(), '3');
|
|
132
|
+
});
|
package/lib/config-defaults.cjs
CHANGED
|
@@ -47,6 +47,17 @@ const DEFAULT_MODEL_PROFILE = 'frontier';
|
|
|
47
47
|
const DEFAULT_SCOPE = 'local';
|
|
48
48
|
const DEFAULT_RESPONSE_LANGUAGE = 'en';
|
|
49
49
|
|
|
50
|
+
const DEFAULT_CONFIG_TREE = Object.freeze({
|
|
51
|
+
scope: DEFAULT_SCOPE,
|
|
52
|
+
model_profile: DEFAULT_MODEL_PROFILE,
|
|
53
|
+
response_language: DEFAULT_RESPONSE_LANGUAGE,
|
|
54
|
+
workflow: DEFAULT_WORKFLOW,
|
|
55
|
+
agents: DEFAULT_AGENTS,
|
|
56
|
+
loop: DEFAULT_LOOP,
|
|
57
|
+
swarm: DEFAULT_SWARM,
|
|
58
|
+
auto_log_learning: DEFAULT_AUTO_LOG_LEARNING,
|
|
59
|
+
});
|
|
60
|
+
|
|
50
61
|
function buildInstallConfig(answers) {
|
|
51
62
|
const a = answers || {};
|
|
52
63
|
return {
|
|
@@ -80,5 +91,6 @@ module.exports = {
|
|
|
80
91
|
DEFAULT_MODEL_PROFILE,
|
|
81
92
|
DEFAULT_SCOPE,
|
|
82
93
|
DEFAULT_RESPONSE_LANGUAGE,
|
|
94
|
+
DEFAULT_CONFIG_TREE,
|
|
83
95
|
buildInstallConfig,
|
|
84
96
|
};
|
package/package.json
CHANGED
|
@@ -363,6 +363,8 @@ After every slice completes, point the operator at `/np:validate-phase $PHASE` t
|
|
|
363
363
|
- Bundle two tasks into one commit (ADR-0004 atomicity).
|
|
364
364
|
- Skip the checkpoint start step — it's the crash-safety primitive `resume-work` depends on.
|
|
365
365
|
- Pass `--no-verify` or `--force` anywhere in the pipeline.
|
|
366
|
+
- **Introduce ad-hoc pre-flight checks beyond the two sanctioned guards** (orphan-checkpoint, empty-milestone). Container-status (`docker ps`), runtime-version probes (`php -v`, `node -v`), DB-connectivity, port-binding — none of these belong in the orchestrator's pre-flight. Tasks edit code; environment failures surface inside the Nubosloop as `verify-red` (→ `spawn-build-fixer`) or as `np-critic-acceptance` `information-missing` findings (→ researcher / plan-checker). They are **never** workflow-level halts.
|
|
367
|
+
- **Declare a "hard blocker" because of infrastructure state.** Container down, PHP version skew, missing image, exited service — all of these are routing signals inside the loop, not reasons to abort the wave. The wave only halts on `commit-task` non-zero, `stuck` after `loop.maxRounds`, or `plan-checker` (locked-decision-violation). Infrastructure mismatch routes via critic findings to researcher/plan-checker; if it's truly out-of-scope for any task in the milestone, the operator handles it separately and re-runs the workflow.
|
|
366
368
|
<!-- /scope_guardrail -->
|
|
367
369
|
|
|
368
370
|
## Output
|