[pitboss] phase 18: Track M.0 — New EntryKind variants: ClassMethod, MessageHandler, ScheduledJob, GraphQLResolver, WebSocket, Middleware, Migration

This commit is contained in:
pitboss 2026-05-20 13:31:11 -05:00
parent 2b96c6005b
commit 1b2f9cb7ca
16 changed files with 750 additions and 178 deletions

View file

@ -24,7 +24,7 @@
use crate::dynamic::environment::{Environment, RuntimeArtifacts};
use crate::dynamic::lang::{ChainStepHarness, ChainStepTerminal, HarnessSource, LangEmitter};
use crate::dynamic::spec::{EntryKind, HarnessSpec, PayloadSlot};
use crate::dynamic::spec::{EntryKindTag, HarnessSpec, PayloadSlot};
use crate::evidence::UnsupportedReason;
use crate::utils::project::DetectedFramework;
use std::path::PathBuf;
@ -41,10 +41,10 @@ pub struct PythonEmitter;
/// argparse `main()` functions. `Function` covers pytest, async
/// coroutines, Celery tasks, and generic module-level functions
/// (positional + kwargs).
const SUPPORTED: &[EntryKind] = &[
EntryKind::Function,
EntryKind::HttpRoute,
EntryKind::CliSubcommand,
const SUPPORTED: &[EntryKindTag] = &[
EntryKindTag::Function,
EntryKindTag::HttpRoute,
EntryKindTag::CliSubcommand,
];
impl LangEmitter for PythonEmitter {
@ -52,13 +52,13 @@ impl LangEmitter for PythonEmitter {
emit(spec)
}
fn entry_kinds_supported(&self) -> &'static [EntryKind] {
fn entry_kinds_supported(&self) -> &'static [EntryKindTag] {
SUPPORTED
}
fn entry_kind_hint(&self, attempted: EntryKind) -> String {
fn entry_kind_hint(&self, attempted: EntryKindTag) -> String {
format!(
"python emitter supports {SUPPORTED:?}; this finding's enclosing context is `EntryKind::{attempted}` — see Phase 12 shape dispatch"
"python emitter supports {SUPPORTED:?}; this finding's enclosing context is `EntryKind::{attempted}` — see Phase 12 / 19 / 20 / 21 shape dispatch"
)
}
@ -177,7 +177,7 @@ impl PythonShape {
/// the legacy substring-only entry-kind heuristic.
pub fn detect(spec: &HarnessSpec, source: &str) -> Self {
let entry = spec.entry_name.as_str();
let kind = spec.entry_kind;
let kind = spec.entry_kind.tag();
// ── Framework-first detection ────────────────────────────────
let has_flask =
@ -224,14 +224,14 @@ impl PythonShape {
return Self::FlaskRoute;
}
if kind == EntryKind::HttpRoute {
if kind == EntryKindTag::HttpRoute {
// The flow-step said HTTP but no framework import was
// detected — fall back to Flask which has the most forgiving
// test client wiring.
return Self::FlaskRoute;
}
if kind == EntryKind::CliSubcommand
if kind == EntryKindTag::CliSubcommand
|| entry == "main"
|| entry == "__main__"
|| source.contains("if __name__ == \"__main__\"")
@ -1925,7 +1925,7 @@ fn module_name(entry_file: &str) -> &str {
#[cfg(test)]
mod tests {
use super::*;
use crate::dynamic::spec::{EntryKind, HarnessSpec, PayloadSlot};
use crate::dynamic::spec::{EntryKind, EntryKindTag, HarnessSpec, PayloadSlot};
use crate::labels::Cap;
use crate::symbol::Lang;
@ -1992,14 +1992,14 @@ mod tests {
#[test]
fn entry_kinds_supported_includes_http_and_cli() {
let kinds = PythonEmitter.entry_kinds_supported();
assert!(kinds.contains(&EntryKind::Function));
assert!(kinds.contains(&EntryKind::HttpRoute));
assert!(kinds.contains(&EntryKind::CliSubcommand));
assert!(kinds.contains(&EntryKindTag::Function));
assert!(kinds.contains(&EntryKindTag::HttpRoute));
assert!(kinds.contains(&EntryKindTag::CliSubcommand));
}
#[test]
fn entry_kind_hint_names_attempted() {
let hint = PythonEmitter.entry_kind_hint(EntryKind::LibraryApi);
let hint = PythonEmitter.entry_kind_hint(EntryKindTag::LibraryApi);
assert!(hint.contains("LibraryApi"));
}