Skip to content

Repository files navigation

HashTag Language (#Tag)

A small, honest notation for stating facts, asking for them, and recording where knowledge came from.

spec: CC BY 4.0 code: Apache-2.0 version: 2.1.0 dependencies: 0

Seven symbols, one job each. Six verbs that carry every relation. Open-world answers, where missing knowledge is reported as unknown and never as false. The reference parser is a single Python file with no dependencies.

#car:vehicle .color[#[racing green]] .doors[4]
#car |has|/part #engine_1:engine
#engine_1:engine .power[120 kW]

#car |has|/part ?part      // -> which parts does the car have?
#car.color?                // -> what colour is it?

#Tag is meant to be the place where the relationships and interfaces between things are written down: not buried in code, not scattered through prose, but in a form a person can read and a machine can check.

Why I built it

I spend my days integrating systems, fitting together parts that were never designed to meet, and I am usually the one who discovers, late, that two of them quietly disagreed about something small. One team measured in millimetres, another in inches. One service promised a reply that another never waited for. A component needed a signal that nothing upstream ever emitted. None of these are hard problems on their own. They are hard because the agreement between the parts was never written down anywhere a machine could check it. It lived in a slide, in someone's memory, in a comment, in a diagram that had already drifted out of date.

I wanted a way to write those agreements down. Not a modelling stack I would need a week to learn, not another database, just a notation small enough to sketch on a whiteboard and precise enough that a script could read it back and tell me whether an assembly held together. Everything I reached for was either too heavy (RDF, OWL, the full semantic-web toolchain) or too loose (a wiki page, a spreadsheet, freeform YAML). So I wrote my own, and used it, and kept cutting it down until nothing was left that did not earn its place.

#Tag is what remained. You can state a fact, ask a question, and attach where the knowledge came from, all in the same tiny grammar. It reads like the documentation you wanted anyway, and it runs like a check. Its one firm rule is honesty about ignorance: if the graph does not know something, the answer is unknown, never false. That is what makes it safe to lay over many parts that each know only their own corner of a system.

I built it for my own work in systems integration and automation. I am publishing the specification so that anyone else who lives at the seams between components can pick it up and use it too.

The seven symbols

Symbol Job Example
# names a thing #car
. a property of that thing #car.color[blue]
- links two things that each exist #car-engine
[ ] holds the value .color[blue]
| | the verb of a relation #car |has| #engine
/ refines the verb #car |has|/part #engine
? the unknown you want reported #car.color?

Six core verbs carry every relation, is has does uses needs knows, and the modifier chain after / is open, so a domain grows its own vocabulary without inventing new syntax. An answer is just an ordinary statement with the unknowns filled in.

The idea: write the seams down

Systems are built by composing parts, and composition breaks at the seams: the interfaces where one part relies on, emits to, or is understood by another. #Tag gives those seams a written form you can query. Declare what each part provides, needs, emits, handles, and promises, then ask the graph whether a given assembly is sound before you build it. Because unknowns stay unknown, a part that has simply not spoken yet never reads as a contradiction, which is exactly what you need when the picture is still being assembled.

What's in this repo

spec/        the canonical specification (v2.0.0 base) + the normative v2.1 delta, CC BY 4.0, plus the full legal code
reference/   tagref.py (parser/store/query) · validate_v2.py + lint.py (conformance + CI lint) · resolve.py
             (bare-ref resolver) — Apache-2.0.  Internals: reference/_README.md
grammars/    the .tag editor grammar (TextMate) for syntax highlighting
examples/    a one-screen taste
ROADMAP.md   what comes next (absence-over-relations queries lead the list)
CHANGELOG.md what changed from the withdrawn 1.0.0 to 2.0.0

Try it (Python 3.10+, no dependencies)

python3 reference/validate_v2.py spec/hashtag-language-spec-v2.0.md   # conformance check
python3 - <<'PY'
from reference.tagref import Store, Registry
st = Store(Registry('demo','0.1.0'))
st.add(open('examples/minimal.tag').read())
print(st.ask("#car |has|/part ?part"))
PY

Expected output:

[{'?part': 'engine_1'}, {'?part': 'oth:?part'}]

The first row is the answer (engine_1); an unbound query variable echoes back as a namespaced placeholder like oth:?part.

Status and roadmap

Version 2.1.0 is the current, stable specification: the 2.0.0 base plus a normative delta adding two optional, declared capabilities — absence over a relation ("which components need a service that nothing provides") and cryptographic provenance annotations. It adds no new symbol, so a 2.0.0 document is a valid 2.1 document unchanged. 2.1 supersedes the withdrawn 1.0.0 lineage; the roadmap tracks later candidates in measured order of demand.

Related tools

Part of a small suite of open tools by Andrew Michelis. See them all at knackmentor.com/work.

  • av-integrity: detect when a vehicle's sensors are lying (an open AV sensor-fusion and integrity monitor).
  • WebClip: save any web page exactly as you saw it (a pixel-faithful page-to-PDF Chrome extension).
  • Markdown Desk: a single-file browser app for reading and working with Markdown.

Built in the open, verified before shipping. The standard behind KnackMentor.

Verifying a release

Every release is tagged and signed under the author's key, and the full source is public here, so you can build from source and compare. Authorship and first-conception are independently timestamped (RFC-3161 / OpenTimestamps) as part of the author's provenance process. Release-artifact attestation via Sigstore is planned. Any certification or curation offered on top stays opt-in, self-hosting is always allowed, and there is no certificate authority you are required to trust.

License

  • Specification (spec/): CC BY 4.0. Read, quote, translate, and implement it, with attribution. The full legal code is vendored in spec/CC-BY-4.0.txt.
  • Reference implementation and tooling (reference/): Apache-2.0. Vendor it freely, patent grant included.

Please cite it with CITATION.cff.

Author

Created and maintained by Andrew P. Michelis, a systems-integration and automation practitioner in Athens, Greece, under KnackMentor, the commercial home for implementations, tooling, integration, and support around the language.

If #Tag is useful to you, adoption and feedback are the best thanks.

About

A small, dependency-free notation for stating facts, querying them, and recording where knowledge came from — seven symbols, six verbs, open-world semantics. CC BY 4.0 spec + Apache-2.0 reference implementation.

Topics

Resources

Contributing

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages