C.W.K.
Stream
Lesson 04 of 04 · published

The Scope Boundary

~12 min · firelink, scope, census, bounded-context

Level 0Cold Ash
0 XP0/32 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"A boundary you can't compute is a boundary you don't have."

One Level Deep, cwk-Prefixed, Nothing Else

A hub that manages 'the family' needs an exact, mechanical answer to 'who is in the family?' Firelink's is deliberately narrow: direct child projects of one projects directory whose names begin with cwk, enumerated exactly one level deep. Not nested repositories. Not the retired attic and its descendants. Not adjacent non-cwk folders. Not the repository template. Not 'ancestors' or 'adjacent repos' that a roster document merely mentions.

This sounds almost too simple, and that's the point. A membership rule you can run in a loop is a rule that can't drift. The moment 'membership' depends on human judgment — 'well, that one kind of counts' — the census stops being reproducible and the hub starts lying about what it manages.

Prose Never Enrolls a Member

Firelink reads roster and network documents to decorate members with titles, one-liners, and lifecycle status. But those documents can also contain lineage notes, 'ancestors', and 'adjacent repos' sections written for humans. A critical rule: that prose never expands the managed set. A roster entry that sits outside the direct-project scope is reference material — not drift, not a card, not something to reconcile. The project root is the scope boundary; the documents decorate what's inside it and are powerless to enroll what's outside.

Why the Attic Stays Out

Retired projects live in an attic directory. They're still on disk, still have history, still matter as memory — and they are deliberately invisible to Firelink. If the census descended into the attic or followed nested repos, it would resurrect dead projects as live cards, probe ports that shouldn't exist, and turn 'we archived that' into 'why is this showing as missing?' The narrow scope is what lets Firelink honestly say 'this is the living family' without dragging every ghost along.

This is the same instinct as a bounded context in domain design: draw a hard line around what you own, and refuse to let a mention across the line pull new things in. Firelink's line is a filesystem rule you can read in five seconds — which is exactly why it holds under a family that keeps growing.

Code

The eligibility rule is a loop, not a judgment call·python
def eligible_members(projects_dir):
    # ONE level only — a plain listdir, never os.walk()
    for entry in sorted(os.listdir(projects_dir)):
        path = projects_dir / entry
        if not path.is_dir():
            continue
        if not entry.startswith("cwk"):     # cwk* only
            continue
        if entry == "_CWK_REPO_TEMPLATE":   # the template is not a member
            continue
        yield entry                          # a managed FamilyMember

# What this rule can NEVER reach, by construction:
#   - _ATTIC/ and its retired descendants
#   - a repo nested inside another repo
#   - an adjacent non-cwk folder
#   - an 'ancestor' a roster file only mentions in prose

External links

Exercise

Take any system that 'manages a set of things' (repos, servers, accounts, devices). Write its membership rule as code you could actually run — no 'and also the important ones' clauses. Then find one place where a human note or a config comment could sneak an extra member in through the side door. That side door is where every 'why is this here?' bug is born.
Hint
If your membership rule contains the word 'usually' or needs a person to adjudicate edge cases, it's not a boundary yet — it's a suggestion. Push it until it's a loop.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.