From c46099a7c73141f292c8cddbaeab333bf5bc279a Mon Sep 17 00:00:00 2001 From: Ion Alpha Date: Sat, 31 Oct 2026 09:06:04 +0000 Subject: [PATCH 1/2] docs: attribute the vendored chat templates and container profiles NOTICE now names the third-party files Flynn ships beside the Chroma lexers: the gpt-oss and Gemma 4 chat templates, copied unchanged from the files OpenAI and Google publish on Hugging Face, and the seccomp profile and AppArmor template derived from moby/profiles. All are Apache-2.0. The template variables record the upstream revision each file was taken from, and a test holds each template to the SHA-256 of that upstream file, so the "copied unchanged" statement fails CI rather than going stale if a template is edited in place. The watch package comment describes the ai! and ai? marker syntax directly. Signed-off-by: Ion Alpha --- NOTICE | 15 +++++++++++++++ internal/inference/launch/template.go | 8 +++++--- internal/inference/launch/template_test.go | 22 ++++++++++++++++++++++ watch/marker.go | 4 ++-- 4 files changed, 44 insertions(+), 5 deletions(-) diff --git a/NOTICE b/NOTICE index d944d6d0..b5ad3e8b 100644 --- a/NOTICE +++ b/NOTICE @@ -7,3 +7,18 @@ The syntax-highlighting definitions in internal/tui/render/lexers are generated from the lexers of Chroma (https://github.com/alecthomas/chroma), Copyright (C) 2017 Alec Thomas, used under the MIT license. See internal/tui/render/lexers for that license text and for how the files are regenerated. + +The chat templates in internal/inference/launch/templates are copied unchanged +from their publishers and used under the Apache License, Version 2.0: +gpt-oss.jinja is the gpt-oss chat template published by OpenAI at +https://huggingface.co/openai/gpt-oss-20b; gemma4.jinja is the Gemma 4 chat +template published by Google at https://huggingface.co/google/gemma-4-12B-it. +The revision of each is recorded in internal/inference/launch/template.go. + +The container security profiles in deploy/seccomp/flynn.json and +deploy/apparmor/flynn-container are Docker's default seccomp profile and +AppArmor template from moby/profiles (https://github.com/moby/profiles), +Copyright The Moby Authors, used under the Apache License, Version 2.0. Each +is modified by one rule, described in dev/container-profiles, which also +pins the upstream commit. Unchanged copies of the upstream files are in +deploy/testdata. diff --git a/internal/inference/launch/template.go b/internal/inference/launch/template.go index 6cb45e1a..1138aaaf 100644 --- a/internal/inference/launch/template.go +++ b/internal/inference/launch/template.go @@ -24,15 +24,17 @@ import ( // from the model. // gptOSSTemplate is OpenAI's published chat template for gpt-oss (the chat_template.jinja -// in openai/gpt-oss-20b, Apache-2.0), byte for byte the template the ggml-org GGUF +// in openai/gpt-oss-20b at revision 6cee5e81ee83917806bbde320786a8fb61efebee, +// Apache-2.0, attributed in NOTICE), byte for byte the template the ggml-org GGUF // conversion embeds. It renders the harmony format, including tool definitions and the // reasoning_effort setting. // //go:embed templates/gpt-oss.jinja var gptOSSTemplate string -// gemma4Template is Google's canonical Gemma 4 chat template (Apache-2.0), as embedded in -// google/gemma-4-12B-it-qat-q4_0-gguf. llama.cpp has no built-in name for Gemma 4; it +// gemma4Template is Google's canonical Gemma 4 chat template (the chat_template.jinja in +// google/gemma-4-12B-it at revision 43c9d014b231474fa7212dbb48a762566c2b255d, Apache-2.0, +// attributed in NOTICE), as embedded in google/gemma-4-12B-it-qat-q4_0-gguf. llama.cpp has no built-in name for Gemma 4; it // recognises the family from the template source, so the source has to be supplied. // //go:embed templates/gemma4.jinja diff --git a/internal/inference/launch/template_test.go b/internal/inference/launch/template_test.go index 1daded3c..441f172d 100644 --- a/internal/inference/launch/template_test.go +++ b/internal/inference/launch/template_test.go @@ -1,6 +1,8 @@ package launch import ( + "crypto/sha256" + "encoding/hex" "strings" "testing" ) @@ -174,3 +176,23 @@ func TestNativeToolCallsFollowsTheRoute(t *testing.T) { t.Error("llama3 runs with --no-jinja and cannot take tools") } } + +// TestEmbeddedTemplatesAreThePublishersOwn holds each embedded template to the SHA-256 of +// the file its publisher ships at the revision recorded on its variable. NOTICE states the +// templates are copied unchanged, and an edit made here would break that statement and +// leave Flynn serving a prompt format no upstream model was trained on. Updating a template +// means taking the publisher's newer file whole, then updating the revision and this digest. +func TestEmbeddedTemplatesAreThePublishersOwn(t *testing.T) { + for name, want := range map[string]string{ + "gpt-oss": "a4c9919cbbd4acdd51ccffe22da049264b1b73e59055fa58811a99efbd7c8146", + "gemma4": "ae53464bf3be25802b3a5b37def7fd89667067d7577049b3b2d74c4d8de4c6d4", + } { + sum := sha256.Sum256([]byte(embeddedTemplates[name])) + if got := hex.EncodeToString(sum[:]); got != want { + t.Errorf("%s template sha256 = %s, want the publisher's %s", name, got, want) + } + } + if len(embeddedTemplates) != 2 { + t.Errorf("embedded templates = %d, want 2: a new one needs its publisher's digest here and a NOTICE entry", len(embeddedTemplates)) + } +} diff --git a/watch/marker.go b/watch/marker.go index 206b6a16..feefbea6 100644 --- a/watch/marker.go +++ b/watch/marker.go @@ -1,6 +1,6 @@ // Package watch turns in-tree source comments into governed run inputs. It tails a -// working tree for aider-style ai! and ai? markers left in trailing comments; when -// one appears it becomes a turn the agent runs, and the marker's file and line are +// working tree for trailing comments that open with an ai! marker (change the code) or +// an ai? marker (answer a question); when one appears it becomes a turn the agent runs, and the marker's file and line are // carried onto the run so its provenance lands in the sealed record like any other // input. The marker is cleared once picked up so the same request never fires twice. package watch From fd11f39ade030beb8e4a23781a74c9d1ddc05692 Mon Sep 17 00:00:00 2001 From: Ion Alpha Date: Sun, 1 Nov 2026 08:01:33 +0000 Subject: [PATCH 2/2] docs: state the Gemma 4 licence in NOTICE and name one template source The Gemma 4 model card (google/gemma-4-12B-it) declares apache-2.0 and links the Gemma 4 licence page, which is the unmodified Apache 2.0 text. The Gemma Terms of Use scope lists only earlier models. NOTICE now says so, so the template and the weights are under the same terms. The gemma4 template comment named the -qat-q4_0-gguf repository as well as the 12B-it repository. The file is byte for byte the chat_template.jinja at the recorded 12B-it revision (sha256 verified), so the comment names that one source. Also wrap two over-long comment lines. Signed-off-by: Ion Alpha --- NOTICE | 8 ++++++++ internal/inference/launch/template.go | 2 +- watch/marker.go | 7 ++++--- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/NOTICE b/NOTICE index b5ad3e8b..930ec534 100644 --- a/NOTICE +++ b/NOTICE @@ -15,6 +15,14 @@ https://huggingface.co/openai/gpt-oss-20b; gemma4.jinja is the Gemma 4 chat template published by Google at https://huggingface.co/google/gemma-4-12B-it. The revision of each is recorded in internal/inference/launch/template.go. +Gemma 4 is licensed by Google under Apache 2.0 (the model card declares +license: apache-2.0 and links https://ai.google.dev/gemma/docs/gemma_4_license, +which is the unmodified Apache 2.0 text). Unlike earlier Gemma releases, it is +not under the Gemma Terms of Use (https://ai.google.dev/gemma/terms), whose +scope lists only those earlier models and which points Gemma 4 to its own +licence. The template and the weights are under the same terms; Flynn does not +distribute the weights. + The container security profiles in deploy/seccomp/flynn.json and deploy/apparmor/flynn-container are Docker's default seccomp profile and AppArmor template from moby/profiles (https://github.com/moby/profiles), diff --git a/internal/inference/launch/template.go b/internal/inference/launch/template.go index 1138aaaf..f803baf9 100644 --- a/internal/inference/launch/template.go +++ b/internal/inference/launch/template.go @@ -34,7 +34,7 @@ var gptOSSTemplate string // gemma4Template is Google's canonical Gemma 4 chat template (the chat_template.jinja in // google/gemma-4-12B-it at revision 43c9d014b231474fa7212dbb48a762566c2b255d, Apache-2.0, -// attributed in NOTICE), as embedded in google/gemma-4-12B-it-qat-q4_0-gguf. llama.cpp has no built-in name for Gemma 4; it +// attributed in NOTICE), byte for byte. llama.cpp has no built-in name for Gemma 4; it // recognises the family from the template source, so the source has to be supplied. // //go:embed templates/gemma4.jinja diff --git a/watch/marker.go b/watch/marker.go index feefbea6..391172a6 100644 --- a/watch/marker.go +++ b/watch/marker.go @@ -1,8 +1,9 @@ // Package watch turns in-tree source comments into governed run inputs. It tails a // working tree for trailing comments that open with an ai! marker (change the code) or -// an ai? marker (answer a question); when one appears it becomes a turn the agent runs, and the marker's file and line are -// carried onto the run so its provenance lands in the sealed record like any other -// input. The marker is cleared once picked up so the same request never fires twice. +// an ai? marker (answer a question); when one appears it becomes a turn the agent runs, +// and the marker's file and line are carried onto the run so its provenance lands in the +// sealed record like any other input. The marker is cleared once picked up so the same +// request never fires twice. package watch import (