Merge branch 'KIN-DOCS-004-backend_dev'
This commit is contained in:
commit
39b6f38414
8 changed files with 66 additions and 12 deletions
|
|
@ -15,6 +15,7 @@ You receive:
|
||||||
|
|
||||||
**Normal mode** (default):
|
**Normal mode** (default):
|
||||||
|
|
||||||
|
0. If PREVIOUS STEP OUTPUT contains a `context_packet` field — read it FIRST before opening any files or analyzing any other context. It contains the essential handoff: architecture decisions, critical file paths, constraints, and unknowns from the prior agent.
|
||||||
1. Read `DESIGN.md`, `core/models.py`, `core/db.py`, `agents/runner.py`, and any MODULES files relevant to the task
|
1. Read `DESIGN.md`, `core/models.py`, `core/db.py`, `agents/runner.py`, and any MODULES files relevant to the task
|
||||||
2. Understand the current architecture — what already exists and what needs to change
|
2. Understand the current architecture — what already exists and what needs to change
|
||||||
3. Design the solution: data model, interfaces, component interactions
|
3. Design the solution: data model, interfaces, component interactions
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ You receive:
|
||||||
|
|
||||||
## Working Mode
|
## Working Mode
|
||||||
|
|
||||||
|
0. If PREVIOUS STEP OUTPUT contains a `context_packet` field — read it FIRST before opening any files or analyzing any other context. It contains the essential handoff: architecture decisions, critical file paths, constraints, and unknowns from the prior agent.
|
||||||
1. Read all relevant backend files before making any changes
|
1. Read all relevant backend files before making any changes
|
||||||
2. Review `PREVIOUS STEP OUTPUT` if it contains an architect spec — follow it precisely
|
2. Review `PREVIOUS STEP OUTPUT` if it contains an architect spec — follow it precisely
|
||||||
3. Implement the feature or fix as described in the task brief
|
3. Implement the feature or fix as described in the task brief
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ You receive:
|
||||||
- Handoff notes clarity — the next department must be able to start without asking questions
|
- Handoff notes clarity — the next department must be able to start without asking questions
|
||||||
- Previous department handoff — build on their work, don't repeat it
|
- Previous department handoff — build on their work, don't repeat it
|
||||||
- Sub-pipeline length — keep it SHORT, 1-4 steps maximum
|
- Sub-pipeline length — keep it SHORT, 1-4 steps maximum
|
||||||
|
- Produce a `context_packet` with exactly 5 fields: `architecture_notes` (string — key arch decisions made), `key_files` (array of file paths critical for the next agent), `constraints` (array of hard technical/business limits discovered), `unknowns` (array of open risks or unresolved questions), `handoff_for` (string — role name of the first worker in sub_pipeline). In the brief for the FIRST worker in sub_pipeline, include this sentence verbatim: «IMPORTANT: Read the `context_packet` field in PREVIOUS STEP OUTPUT FIRST, before any other section or file.»
|
||||||
|
|
||||||
**Department-specific guidance:**
|
**Department-specific guidance:**
|
||||||
|
|
||||||
|
|
@ -46,6 +47,7 @@ You receive:
|
||||||
- Each worker brief is self-contained — no "see above" references
|
- Each worker brief is self-contained — no "see above" references
|
||||||
- Artifacts list is complete and specific
|
- Artifacts list is complete and specific
|
||||||
- Handoff notes are actionable for the next department
|
- Handoff notes are actionable for the next department
|
||||||
|
- `context_packet` is present with all 5 required fields; `handoff_for` is non-empty and matches the role in `sub_pipeline[0]`; first worker brief contains explicit instruction to read `context_packet` first
|
||||||
|
|
||||||
## Return Format
|
## Return Format
|
||||||
|
|
||||||
|
|
@ -72,7 +74,14 @@ Return ONLY valid JSON (no markdown, no explanation):
|
||||||
"schemas": [],
|
"schemas": [],
|
||||||
"notes": "Added feature with full test coverage. All tests pass."
|
"notes": "Added feature with full test coverage. All tests pass."
|
||||||
},
|
},
|
||||||
"handoff_notes": "Backend implementation complete. Tests passing. Frontend needs to call POST /api/feature with {field: value} body."
|
"handoff_notes": "Backend implementation complete. Tests passing. Frontend needs to call POST /api/feature with {field: value} body.",
|
||||||
|
"context_packet": {
|
||||||
|
"architecture_notes": "Used existing models.py pattern, no ORM, raw sqlite3",
|
||||||
|
"key_files": ["core/models.py", "web/api.py"],
|
||||||
|
"constraints": ["All DB columns must have DEFAULT values", "No new Python deps"],
|
||||||
|
"unknowns": ["Frontend integration not yet verified"],
|
||||||
|
"handoff_for": "backend_dev"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ You receive:
|
||||||
|
|
||||||
## Working Mode
|
## Working Mode
|
||||||
|
|
||||||
|
0. If PREVIOUS STEP OUTPUT contains a `context_packet` field — read it FIRST before opening any files or analyzing any other context. It contains the essential handoff: architecture decisions, critical file paths, constraints, and unknowns from the prior agent.
|
||||||
1. Read all relevant frontend files before making any changes
|
1. Read all relevant frontend files before making any changes
|
||||||
2. Review `PREVIOUS STEP OUTPUT` if it contains an architect spec — follow it precisely
|
2. Review `PREVIOUS STEP OUTPUT` if it contains an architect spec — follow it precisely
|
||||||
3. Implement the feature or fix as described in the task brief
|
3. Implement the feature or fix as described in the task brief
|
||||||
|
|
|
||||||
|
|
@ -1347,14 +1347,29 @@ def _execute_department_head_step(
|
||||||
role = step["role"]
|
role = step["role"]
|
||||||
dept_name = role.replace("_head", "")
|
dept_name = role.replace("_head", "")
|
||||||
|
|
||||||
# Build initial context for workers: dept head's plan + artifacts
|
# Extract context_packet (KIN-DOCS-004): fail-open if missing
|
||||||
dept_plan_context = json.dumps({
|
context_packet = parsed.get("context_packet")
|
||||||
"department_head_plan": {
|
if context_packet is None and parent_pipeline_id:
|
||||||
|
try:
|
||||||
|
models.write_log(
|
||||||
|
conn, parent_pipeline_id,
|
||||||
|
f"Dept {step['role']}: context_packet missing from output — handoff quality degraded",
|
||||||
|
level="WARN",
|
||||||
|
extra={"role": step["role"]},
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Build initial context for workers: context_packet first, then dept head's plan
|
||||||
|
dept_plan_context_dict: dict = {}
|
||||||
|
if context_packet is not None:
|
||||||
|
dept_plan_context_dict["context_packet"] = context_packet
|
||||||
|
dept_plan_context_dict["department_head_plan"] = {
|
||||||
"department": dept_name,
|
"department": dept_name,
|
||||||
"artifacts": parsed.get("artifacts", {}),
|
"artifacts": parsed.get("artifacts", {}),
|
||||||
"handoff_notes": parsed.get("handoff_notes", ""),
|
"handoff_notes": parsed.get("handoff_notes", ""),
|
||||||
},
|
}
|
||||||
}, ensure_ascii=False)
|
dept_plan_context = json.dumps(dept_plan_context_dict, ensure_ascii=False)
|
||||||
|
|
||||||
# KIN-084: log sub-pipeline start
|
# KIN-084: log sub-pipeline start
|
||||||
if parent_pipeline_id:
|
if parent_pipeline_id:
|
||||||
|
|
@ -1429,6 +1444,7 @@ def _execute_department_head_step(
|
||||||
decisions_made=decisions_made,
|
decisions_made=decisions_made,
|
||||||
blockers=[],
|
blockers=[],
|
||||||
status=handoff_status,
|
status=handoff_status,
|
||||||
|
context_packet=context_packet,
|
||||||
)
|
)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass # Handoff save errors must never block pipeline
|
pass # Handoff save errors must never block pipeline
|
||||||
|
|
@ -1438,6 +1454,7 @@ def _execute_department_head_step(
|
||||||
"from_department": dept_name,
|
"from_department": dept_name,
|
||||||
"handoff_notes": parsed.get("handoff_notes", ""),
|
"handoff_notes": parsed.get("handoff_notes", ""),
|
||||||
"artifacts": parsed.get("artifacts", {}),
|
"artifacts": parsed.get("artifacts", {}),
|
||||||
|
"context_packet": context_packet,
|
||||||
"sub_pipeline_summary": {
|
"sub_pipeline_summary": {
|
||||||
"steps_completed": sub_result.get("steps_completed", 0),
|
"steps_completed": sub_result.get("steps_completed", 0),
|
||||||
"success": sub_result.get("success", False),
|
"success": sub_result.get("success", False),
|
||||||
|
|
|
||||||
|
|
@ -181,6 +181,8 @@ specialists:
|
||||||
context_rules:
|
context_rules:
|
||||||
decisions: all
|
decisions: all
|
||||||
modules: all
|
modules: all
|
||||||
|
output_schema:
|
||||||
|
context_packet: "{ architecture_notes: string, key_files: array, constraints: array, unknowns: array, handoff_for: string }"
|
||||||
|
|
||||||
frontend_head:
|
frontend_head:
|
||||||
name: "Frontend Department Head"
|
name: "Frontend Department Head"
|
||||||
|
|
@ -193,6 +195,8 @@ specialists:
|
||||||
context_rules:
|
context_rules:
|
||||||
decisions: all
|
decisions: all
|
||||||
modules: all
|
modules: all
|
||||||
|
output_schema:
|
||||||
|
context_packet: "{ architecture_notes: string, key_files: array, constraints: array, unknowns: array, handoff_for: string }"
|
||||||
|
|
||||||
qa_head:
|
qa_head:
|
||||||
name: "QA Department Head"
|
name: "QA Department Head"
|
||||||
|
|
@ -204,6 +208,8 @@ specialists:
|
||||||
permissions: read_only
|
permissions: read_only
|
||||||
context_rules:
|
context_rules:
|
||||||
decisions: all
|
decisions: all
|
||||||
|
output_schema:
|
||||||
|
context_packet: "{ architecture_notes: string, key_files: array, constraints: array, unknowns: array, handoff_for: string }"
|
||||||
|
|
||||||
security_head:
|
security_head:
|
||||||
name: "Security Department Head"
|
name: "Security Department Head"
|
||||||
|
|
@ -215,6 +221,8 @@ specialists:
|
||||||
permissions: read_only
|
permissions: read_only
|
||||||
context_rules:
|
context_rules:
|
||||||
decisions_category: security
|
decisions_category: security
|
||||||
|
output_schema:
|
||||||
|
context_packet: "{ architecture_notes: string, key_files: array, constraints: array, unknowns: array, handoff_for: string }"
|
||||||
|
|
||||||
infra_head:
|
infra_head:
|
||||||
name: "Infrastructure Department Head"
|
name: "Infrastructure Department Head"
|
||||||
|
|
@ -226,6 +234,8 @@ specialists:
|
||||||
permissions: read_only
|
permissions: read_only
|
||||||
context_rules:
|
context_rules:
|
||||||
decisions: all
|
decisions: all
|
||||||
|
output_schema:
|
||||||
|
context_packet: "{ architecture_notes: string, key_files: array, constraints: array, unknowns: array, handoff_for: string }"
|
||||||
|
|
||||||
knowledge_synthesizer:
|
knowledge_synthesizer:
|
||||||
name: "Knowledge Synthesizer"
|
name: "Knowledge Synthesizer"
|
||||||
|
|
@ -252,6 +262,8 @@ specialists:
|
||||||
permissions: read_only
|
permissions: read_only
|
||||||
context_rules:
|
context_rules:
|
||||||
decisions: all
|
decisions: all
|
||||||
|
output_schema:
|
||||||
|
context_packet: "{ architecture_notes: string, key_files: array, constraints: array, unknowns: array, handoff_for: string }"
|
||||||
|
|
||||||
marketing_head:
|
marketing_head:
|
||||||
name: "Marketing Department Head"
|
name: "Marketing Department Head"
|
||||||
|
|
@ -264,6 +276,8 @@ specialists:
|
||||||
context_rules:
|
context_rules:
|
||||||
decisions: all
|
decisions: all
|
||||||
modules: all
|
modules: all
|
||||||
|
output_schema:
|
||||||
|
context_packet: "{ architecture_notes: string, key_files: array, constraints: array, unknowns: array, handoff_for: string }"
|
||||||
|
|
||||||
# Departments — PM uses these when routing complex cross-domain tasks to department heads
|
# Departments — PM uses these when routing complex cross-domain tasks to department heads
|
||||||
departments:
|
departments:
|
||||||
|
|
|
||||||
|
|
@ -165,6 +165,7 @@ CREATE TABLE IF NOT EXISTS department_handoffs (
|
||||||
artifacts JSON,
|
artifacts JSON,
|
||||||
decisions_made JSON,
|
decisions_made JSON,
|
||||||
blockers JSON,
|
blockers JSON,
|
||||||
|
context_packet JSON DEFAULT NULL,
|
||||||
status TEXT DEFAULT 'pending',
|
status TEXT DEFAULT 'pending',
|
||||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
);
|
);
|
||||||
|
|
@ -703,6 +704,13 @@ def _migrate(conn: sqlite3.Connection):
|
||||||
""")
|
""")
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
|
# Add context_packet column to department_handoffs (KIN-DOCS-004)
|
||||||
|
if "department_handoffs" in existing_tables:
|
||||||
|
handoff_cols = {r[1] for r in conn.execute("PRAGMA table_info(department_handoffs)").fetchall()}
|
||||||
|
if "context_packet" not in handoff_cols:
|
||||||
|
conn.execute("ALTER TABLE department_handoffs ADD COLUMN context_packet JSON DEFAULT NULL")
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
# Add test_command column to projects (KIN-ARCH-008); NULL = auto-detect (KIN-101)
|
# Add test_command column to projects (KIN-ARCH-008); NULL = auto-detect (KIN-101)
|
||||||
projects_cols = {row["name"] for row in conn.execute("PRAGMA table_info(projects)")}
|
projects_cols = {row["name"] for row in conn.execute("PRAGMA table_info(projects)")}
|
||||||
if "test_command" not in projects_cols:
|
if "test_command" not in projects_cols:
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ _JSON_COLUMNS: frozenset[str] = frozenset({
|
||||||
"dependencies",
|
"dependencies",
|
||||||
"steps",
|
"steps",
|
||||||
"artifacts", "decisions_made", "blockers",
|
"artifacts", "decisions_made", "blockers",
|
||||||
|
"context_packet",
|
||||||
"extra_json",
|
"extra_json",
|
||||||
"pending_actions",
|
"pending_actions",
|
||||||
})
|
})
|
||||||
|
|
@ -1191,14 +1192,16 @@ def create_handoff(
|
||||||
decisions_made: list | None = None,
|
decisions_made: list | None = None,
|
||||||
blockers: list | None = None,
|
blockers: list | None = None,
|
||||||
status: str = "pending",
|
status: str = "pending",
|
||||||
|
context_packet: dict | list | None = None,
|
||||||
) -> dict:
|
) -> dict:
|
||||||
"""Record a department handoff with artifacts for inter-department context."""
|
"""Record a department handoff with artifacts for inter-department context."""
|
||||||
cur = conn.execute(
|
cur = conn.execute(
|
||||||
"""INSERT INTO department_handoffs
|
"""INSERT INTO department_handoffs
|
||||||
(pipeline_id, task_id, from_department, to_department, artifacts, decisions_made, blockers, status)
|
(pipeline_id, task_id, from_department, to_department, artifacts, decisions_made, blockers, context_packet, status)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)""",
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||||
(pipeline_id, task_id, from_department, to_department,
|
(pipeline_id, task_id, from_department, to_department,
|
||||||
_json_encode(artifacts), _json_encode(decisions_made), _json_encode(blockers), status),
|
_json_encode(artifacts), _json_encode(decisions_made), _json_encode(blockers),
|
||||||
|
_json_encode(context_packet), status),
|
||||||
)
|
)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
row = conn.execute(
|
row = conn.execute(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue