Index: doc/proposals/modules-gen-hdr/.gitignore
===================================================================
--- doc/proposals/modules-gen-hdr/.gitignore	(revision 4706491482b34debb8b26fe79bcb509e44e2f031)
+++ doc/proposals/modules-gen-hdr/.gitignore	(revision 4706491482b34debb8b26fe79bcb509e44e2f031)
@@ -0,0 +1,6 @@
+!Makefile
+a.out
+*.tdcl.h
+*.defn.h
+*.impl.c
+*.d
Index: doc/proposals/modules-gen-hdr/Makefile
===================================================================
--- doc/proposals/modules-gen-hdr/Makefile	(revision 4706491482b34debb8b26fe79bcb509e44e2f031)
+++ doc/proposals/modules-gen-hdr/Makefile	(revision 4706491482b34debb8b26fe79bcb509e44e2f031)
@@ -0,0 +1,121 @@
+# a demo is a name that can be make'd into an a.out,
+# that designates a collection of compile units,
+# each with a corresponding .src.c + .o file pair
+SOURCES_IN_DEMO=$(wildcard $1/*.src.c)
+OBJECTS_IN_DEMO=$(patsubst %.src.c,%.o,$(call SOURCES_IN_DEMO,$1))
+ALL_OBJECTS=$(foreach demo,$(DEMOS),$(call OBJECTS_IN_DEMO,$(demo)))
+
+# each recursive subdir gives a demo
+# a demo name may have slashes in middle, but not at start or end (foo, foo/bar)
+DIRS_REC=$(shell find ./* -type d)
+DEMOS_FROM_DIRS=$(patsubst ./%,%,$1)
+DEMO_OF_FILE=$(patsubst %/,%,$(dir $1))
+DEMOS=$(call DEMOS_FROM_DIRS,$(DIRS_REC))
+
+# demos of working code build under target `all`
+# default assumption = demo is working
+# demos named err-% recursively opt out
+ERR_DIRPATS=err-%
+DEMOS_NONERR=$(filter-out $(ERR_DIRPATS),$(DEMOS))
+DEMO_EXECS_NONERR=$(DEMOS_NONERR:=/a.out)
+
+# a recourse is a designated sub-demo of an error case
+# that is expected to build successfully
+RECOURSE_DIRPATS=%/recourse-classic
+DEMOS_RECOURSE=$(filter $(RECOURSE_DIRPATS),$(DEMOS))
+DEMO_EXECS_RECOURSE=$(DEMOS_RECOURSE:=/a.out)
+
+# non-err and recourse demos try to build by default
+ALL=$(DEMO_EXECS_NONERR) $(DEMO_EXECS_RECOURSE)
+
+# a shred is a *.c or *.h file generated from a *.src.c
+SHRED_EXTS=.impl.c .defn.h .tdcl.h
+SHREDS_OF_FILE=$(foreach st,$(SHRED_EXTS),$(1:=$(st)))
+SHREDS_IN_DEMO=$(foreach src,$(call SOURCES_IN_DEMO,$1),$(call SHREDS_OF_FILE,$(src:.src.c=)))
+SHREDS_IN_DEMO_OF_FILE=$(call SHREDS_IN_DEMO,$(call DEMO_OF_FILE,$1))
+
+# a 'classic' demo builds without shredding
+CLASSIC_DIRPATS=%-classic
+DEMOS_CLASSIC=$(filter $(CLASSIC_DIRPATS),$(DEMOS))
+DEMOS_NONSHRED=$(DEMOS_CLASSIC)
+OBJECTS_NONSHRED=$(foreach demo,$(DEMOS_NONSHRED),$(call OBJECTS_IN_DEMO,$(demo)))
+
+# everything else builds via shredding
+DEMOS_SHRED=$(filter-out $(RECOURSE_DIRPATS),$(DEMOS))
+OBJECTS_SHRED=$(foreach demo,$(DEMOS_SHRED),$(call OBJECTS_IN_DEMO,$(demo)))
+ALL_SHREDS=$(foreach demo,$(DEMOS),$(call SHREDS_IN_DEMO,$(demo)))
+
+
+CC=gcc
+CPPP=./cfa-cppp
+CQFLAGS=-Wall -Wextra -Werror
+
+
+.SECONDEXPANSION: # enable dynamic prereqs from $$
+.SUFFIXES: # disable traditional rules like make .o from .c by calling $(CC)
+
+
+all: $(ALL)
+
+# troubleshooting, e.g. `make echo_DEMOS` runs `echo $(DEMOS)`
+echo_% :
+	@echo '$($(@:echo_%=%))'
+
+#
+# demo
+#
+
+%/a.out : DEMO=$(@:/a.out=)
+%/a.out : OBJECTS=$(call OBJECTS_IN_DEMO,$(DEMO))
+%/a.out : $$(OBJECTS)
+	$(CC) $(OBJECTS) -o $@ $(CFLAGS) $(CQFLAGS)
+
+$(DEMOS) : $$@/a.out
+
+#
+# object
+#
+
+# object of regular, shredded, demo
+# each CU depends on all other CUs' shreds
+# conservative for rebuild (obviates -MMD), but helps do initial build
+$(OBJECTS_SHRED) : CC_SRC=$(@:.o=.impl.c)
+$(OBJECTS_SHRED) : SHREDS=$(call SHREDS_IN_DEMO_OF_FILE,$@)
+$(OBJECTS_SHRED) : $$(SHREDS)
+
+# of nonshredded demo
+$(OBJECTS_NONSHRED) : CC_SRC=$(@:.o=.src.c)
+$(OBJECTS_NONSHRED) : CQFLAGS+= -MMD
+
+-include $(OBJECTS_NONSHRED:.o=.d)
+
+$(ALL_OBJECTS) :
+	$(CC) $(CC_SRC) -c -o $@ $(CFLAGS) $(CQFLAGS)
+
+#
+# shred
+#
+
+define SINGLE_SHREDEXT_RULE
+%$1: %.src.c $(CPPP)
+	$(CPPP) $$@
+endef
+
+$(foreach sfx,$(call SHREDS_OF_FILE,@),$(eval $(call SINGLE_SHREDEXT_RULE,$(sfx:@%=%))))
+
+#
+# clean, misc
+#
+
+# 2-line body is significant; \n ending 1st line is literal
+define newline
+
+
+endef
+
+CLEANPATS=$(call SHREDS_OF_FILE,*) *.o *.d a.out
+clean:
+	$(foreach p,$(CLEANPATS),find . -name '$p' -type f -print -delete$(newline))
+
+.PRECIOUS: %.tdcl.h %.defn.h %.impl.c
+.PHONY: all echo_% clean
Index: doc/proposals/modules-gen-hdr/README
===================================================================
--- doc/proposals/modules-gen-hdr/README	(revision b28ce93ef6648a426d1fb594f74b51bfeda9976c)
+++ doc/proposals/modules-gen-hdr/README	(revision 4706491482b34debb8b26fe79bcb509e44e2f031)
@@ -10,5 +10,7 @@
 
 Terminology
+- auto: as in C, "exported from here;" different from `extern`, which means "exported by someone else" in C
 - shred: "Shredding foo.src.c" means producing the "foo" Key Intermediates from the "foo" Input.
+- value: the opposite of a type, includes function
 - vicious: cyclic dependency that cannot be bootstrapped with the tools under POC
 
@@ -44,6 +46,7 @@
   - (including) expect recourse like multiple manual header fragments to resolve
 - vicious*/recourse-classic
+  - example of a manual header split that resolves the circularity
 - vicious*/recourse-proposed
-
+  - same split, given in a plausible headerless representation that's not demo-implemented
 
 In scope
@@ -74,5 +77,5 @@
 
 Language additions modelled
-- (The proposal is to include nicer versions of these placeholders to CFA)
+- (The proposal is to add nicer versions of these placeholders to CFA)
 - module imports (#import), where `foo` corresponds with foo.c; one of:
 - `#import static foo`: this implementation depends on foo's interface
