---
title: 'Graphical Interface and Command Line'
source: 'https://academia.sh/en/courses/it-fundamentals/graphical-interface-and-command-line'
course: 'Information Technology and Systems Fundamentals'
language: en
updated: '2026-10-21T05:02:56+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Writes the trace a management job leaves with three numbers: records dropped, items appearing in the audit trail, reproducibility'
    - 'Distinguishes whether the audit trail comes from the form or from the subsystem keeping its own record'
    - 'Computes the trace and operation cost of repeating the same job across many machines'
---

# Graphical Interface and Command Line

Counting the trace the same ten management jobs leave in two management forms: the graphical interface and the command line tying at 11 items appearing in the audit trail, three jobs leaving no trace at all in either form, the reproducible job count needing a script and a repository to rise from 0 to 10, and manual operations across forty machines dropping from 400 to 10.

The previous lesson measured the expressive power of permission models and left one question
open: a permission line **changing** is also an event. Policy changes when ownership is
compromised or when an admin changes a rule; what that change leaves behind is something just as
measurable as the permission line itself.

This lesson performs the same management jobs in two forms — through a graphical interface and
through the command line — and counts the trace items each one leaves behind.

## A Trace Is a Number

When a management job finishes, what is left behind is written with three separate measures.

**How many records fall.** At the end of the job, how many separate places a trace forms in: the
subsystem's own record, the interface's own log, the shell history, a script file, a repository
commit, a change ticket.

**How many appear in the audit trail.** Not all records are equal. If a record can be deleted by
the person who did the job, it does not count as an audit trail item. Shell history is the
user's own file; the interface's local log rotates and is not retained. **A record that is not
persistent is not a trace — it is a reminder.**

**How many can be reproduced.** If a record carries exactly what the change was, the same change
can be repeated identically on another machine or rolled back. A record saying "a user was added"
is not the same thing as a record carrying the definition of that addition.

## Ten Jobs, Three Forms

The example is ten management jobs performed on the branch servers of the fictional **regional
measurement network**. Both the jobs and the record scheme are fictional; the table below is a
**model** — there is no real interface, shell, or product.

**HO23:** the management job set is 10, and each job can be done in three forms. **HO24:** the
record type is 6; the `persistent` field says the record cannot be deleted by the person who did
the job and appears in the audit trail, the `reproduces` field says the record is enough to
reproduce the change. **HO25:** the system record and the change ticket are
**form-independent** — if the subsystem doing the job keeps its own record, it keeps it in all
three forms. **HO26:** a form only adds its own extra records. **HO27:** the same job is repeated
across forty machines; in the script-and-repo form, the definition is written once and run forty
times.

```js
// it/trace.mjs — the trace the same management job leaves in two forms (model): fictional
// measurement network, no real interface, shell, or product. No randomness.

// Record types. persistent: cannot be deleted by the user, appears in the audit trail.
// reproduces: the record itself is enough to reproduce the change.
export const TYPE = {
  "system-record": { persistent: true, reproduces: false },
  "change-ticket": { persistent: true, reproduces: false },
  "interface-log": { persistent: false, reproduces: false },
  "shell-history": { persistent: false, reproduces: false },
  "script-file": { persistent: false, reproduces: true },
  "repo-commit": { persistent: true, reproduces: true },
};

// Records each form adds to every job. The system record and the change ticket are form-independent.
export const FORM = { graphical: ["interface-log"], command: ["shell-history"],
  "script-repo": ["shell-history", "script-file", "repo-commit"] };

// system: does the subsystem doing the job keep its own record. ticket: is the job tied to a change ticket.
export const JOB = `
  add-user             yes  yes
  change-permission    no   yes
  stop-service         yes  yes
  firewall-rule        yes  yes
  mount-disk-volume    no   no
  install-software     yes  yes
  set-clock            yes  no
  install-certificate  no   no
  take-backup          yes  no
  review-log           no   no`
  .trim().split("\n").map((r) => {
    const [name, system, ticket] = r.trim().split(/\s+/);
    return { name, system: system === "yes", ticket: ticket === "yes" };
  });

export const records = (job, form) => [...(job.system ? ["system-record"] : []),
  ...(job.ticket ? ["change-ticket"] : []), ...FORM[form]];

export function measure(form) {
  const r = JOB.map((job) => records(job, form));
  const persistent = r.map((x) => x.filter((t) => TYPE[t].persistent).length);
  return { records: r.reduce((a, x) => a + x.length, 0),
    inAudit: persistent.reduce((a, x) => a + x, 0),
    notInAudit: r.reduce((a, x) => a + x.filter((t) => !TYPE[t].persistent).length, 0),
    traceless: persistent.filter((x) => x === 0).length,
    reproducible: r.filter((x) => x.some((t) => TYPE[t].reproduces && TYPE[t].persistent)).length };
}
```

```js
// it/tracemeasure.mjs — how many records fall, how many appear in the audit trail, how many can be reproduced.
import { TYPE, FORM, JOB, records, measure } from "./trace.mjs";

const write = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join(""));
const B = Object.keys(FORM);
const MACHINES = 40;

console.log(`${JOB.length} management jobs x ${B.length} forms; record types ${Object.keys(TYPE).length}: ` +
  Object.entries(TYPE).map(([t, v]) => `${t}${v.persistent ? " (persistent)" : ""}`).join(", "));

const A = [-24, -8, -8, 11, 10, 13];
console.log("\n1. record items per job (in parentheses: items appearing in the audit trail)");
write(A, "job", "system", "ticket", ...B);
for (const job of JOB) {
  const h = (b) => { const r = records(job, b);
    return `${r.length} (${r.filter((t) => TYPE[t].persistent).length})`; };
  write(A, job.name, job.system ? "yes" : "no", job.ticket ? "yes" : "no", ...B.map(h));
}

const C = [-40, 11, 10, 13];
console.log("\n2. total per form");
write(C, "measure", ...B);
const R = Object.fromEntries(B.map((b) => [b, measure(b)]));
for (const [name, f] of [["record items dropped", (r) => r.records],
  ["items appearing in the audit trail", (r) => r.inAudit],
  ["items not appearing in the audit trail", (r) => r.notInAudit],
  ["jobs leaving no audit trail", (r) => `${r.traceless}/${JOB.length}`],
  ["reproducible jobs", (r) => `${r.reproducible}/${JOB.length}`]])
  write(C, name, ...B.map((b) => f(R[b])));

const D = [-40, 11, 10, 13];
console.log(`\n3. the same job repeated across ${MACHINES} machines`);
write(D, "measure", ...B);
for (const [name, f] of [["manual operations", (b) => (b === "script-repo" ? JOB.length : JOB.length * MACHINES)],
  ["place storing the change definition", (b) => (b === "script-repo" ? 1 : 0)],
  ["items appearing in the audit trail", (b) => R[b].inAudit * MACHINES]])
  write(D, name, ...B.map(f));
```

```
10 management jobs x 3 forms; record types 6: system-record (persistent), change-ticket (persistent), interface-log, shell-history, script-file, repo-commit (persistent)

1. record items per job (in parentheses: items appearing in the audit trail)
job                     system  ticket    graphical   command  script-repo
add-user                yes     yes           3 (2)     3 (2)        5 (3)
change-permission       no      yes           2 (1)     2 (1)        4 (2)
stop-service            yes     yes           3 (2)     3 (2)        5 (3)
firewall-rule           yes     yes           3 (2)     3 (2)        5 (3)
mount-disk-volume       no      no            1 (0)     1 (0)        3 (1)
install-software        yes     yes           3 (2)     3 (2)        5 (3)
set-clock               yes     no            2 (1)     2 (1)        4 (2)
install-certificate     no      no            1 (0)     1 (0)        3 (1)
take-backup             yes     no            2 (1)     2 (1)        4 (2)
review-log              no      no            1 (0)     1 (0)        3 (1)

2. total per form
measure                                   graphical   command  script-repo
record items dropped                             21        21           41
items appearing in the audit trail               11        11           21
items not appearing in the audit trail           10        10           20
jobs leaving no audit trail                    3/10      3/10         0/10
reproducible jobs                              0/10      0/10        10/10

3. the same job repeated across 40 machines
measure                                   graphical   command  script-repo
manual operations                               400       400           10
place storing the change definition               0         0            1
items appearing in the audit trail              440       440          840
```
The numbers belong to the **measurement** class; their inputs are HO23–HO27.

## Two Forms Leave the Same Trace

The first three rows of the second table give an unexpected equality. The graphical interface
and the command line produce **the same numbers** on the same ten jobs: 21 record items, of
which **11** appear in the audit trail and 10 do not. The fourth row is the same too: in both
forms, **3 jobs** leave no audit trail at all.

The reason is in the first table. The items that appear in the audit trail come from only two
types: the subsystem's own record and the change ticket. Both are **form-independent**. Doing a
job through the graphical interface does not turn a job the subsystem does not record into a
recorded one; doing the same job through the command does not either.

The item each form adds — the interface's local log and the shell history — is not persistent.
Both can be deleted by the person who did the job, and neither carries the definition of the
change. This is why neither counts as an audit trail item; they show up as 10 in the columns, and
that 10 contributes nothing to the measure.

**"It was done from the command line, so there is a record" is an assumption, and it is wrong in
the model.** Shell history is a file in the user's home directory: it can be turned off,
deleted, edited. An audit trail item sits in a place that is not under the control of the person
who left the trace.

## The Difference Is in Reproducibility

The fifth row separates the two forms for the first time — but what it separates is not
graphical from command, it is **scripted from unscripted**. The number of reproducible jobs is
0/10 in the graphical interface, also 0/10 for a manually typed command, and 10/10 in the
script-and-repo form.

What separates a manually typed command from a script is that its definition sits nowhere. The
command runs, leaves its result, and disappears itself. Shell history keeps the command lines,
but a history is not a definition: it does not write down the order, the context, which machine
it ran on, or which attempt failed.

In the script-and-repo form, two items are added, and the two work together. The script file
reproduces the change but is not itself persistent — it sits on disk and can be altered. The
repository commit is both persistent and carries the definition. This is why the measure looks
for the `reproduces` and `persistent` fields together: **reproducibility does not depend on a
definition existing — it depends on the definition sitting in a place that cannot be altered.**

The same row also hides a cost. In the script-and-repo form, the records dropped rise to 41 and
the items not appearing in the audit trail rise to 20. This item not appearing in the audit
trail doubling is not a loss — the items added are already accounted for in the repository commit
— but it raises the number of places to look. In an incident, three separate record sets are
compared, and that comparison is itself a job.

## Three Jobs Leave No Trace

The **3/10** in the fourth row is the same in both forms and is the measurement's most direct
output. Behind mounting a disk volume, installing a certificate, and reviewing a log there is
neither a subsystem record nor a change ticket; when these three jobs are done, only a
deletable item is left behind.

What these three jobs share is that two of them do not look like a configuration change.
Reviewing a log is not a change — but which records were read by whom is one of the questions
asked in an incident investigation. Installing a certificate looks like copying a file, yet it
changes who the machine trusts.

In the script-and-repo form, this number drops to 0/10, because the repository commit depends on
the job, not the form: even if the subsystem does not keep a record, the change is written down
somewhere. **The fix for a job that leaves no trace is not changing the interface — it is
turning the job into a defined change.**

## Forty Machines

The third table adds scale. When the ten jobs are repeated across forty branch servers, the
number of manual operations is **400** in the graphical and command forms and **10** in the
script-and-repo form; the definition is written once and run forty times.

The number of places storing the change definition is 0, 0, and 1. Zero means there is **no
definition to compare against** to see whether the forty machines have drifted from one another;
drift can only be found by reading the machines one by one. If a definition exists, drift is
asked as the difference between the definition and the machine.

The items appearing in the audit trail rise to 440, 440, and 840. This number does not improve
as it grows; it is the number of items that must be read. The measure's third column is therefore
not the raw record count but **the number of questions answered per record**: 440 items answer
"who, when"; 400 of the 840 items also answer "exactly what."

## The Record's Readability Is a Separate Item

The number of items appearing in the audit trail assumes those items can be read together. The
440 records across forty machines turn into a single narrative only under two conditions: the
records sharing a common time axis, and the same job being referred to by the same name across
different machines.

The first condition depends on the `time-synchronization` item from the previous lesson. If that
item is off, the records of two machines cannot be ordered, and the question "which happened
first" goes unanswered; the number of items appearing in the audit trail keeps being written as
440, but the number of questions it answers drops. The second condition concerns naming: if the
same job is recorded under one name on one machine and a different name on another, the items
cannot be aggregated.

This is why the trace measure is written with three numbers, not two: how many items drop, how
many are persistent, and how many of the persistent ones are **comparable**. The first two
numbers depend on the form and the subsystem; the third depends on install-time items. When the
third number is not measured, the audit trail is just a pile of records.

## The Choice of Form Depends on How Often the Job Repeats

The table does not rank one form above the other. The numbers separate three situations.

**A one-off job with no definition yet.** While hunting for the cause of a problem, which setting
will change is not known in advance; here, the graphical interface's missing trace is not a cost,
because there is no definition to repeat. This kind of job is not repeated across forty machines.

**A job that will be repeated across forty machines.** In this situation, the third table points
in a single direction: the gap between 400 manual operations and 10 is less about the operation
count and more about **how measurable the drift is**. On forty machines with no definition,
drift cannot be found.

**A job that is subject to audit.** What decides here is not the form but whether a subsystem
record exists behind the job. If the subsystem does not keep a record, no form fixes this; the
job must be turned into a defined change.

The common lesson across the three situations is this: **the choice of form is not a habit — it
is a decision determined by how often the job repeats and by the audit requirement.** Once it is
written down how many of the measurement network's ten jobs fall into which class, which job needs
to be scripted stops being a matter of debate.

## Summary

- A management job's trace is written with three numbers: record items dropped, how many of them
  appear in the audit trail, and how many jobs can be reproduced.
- The graphical interface and the command line give the same numbers on the ten jobs: 21 records,
  11 audit trail items, 3 jobs leave no trace at all. The audit trail comes not from the form but
  from the subsystem keeping its own record and from the change ticket.
- The item each form adds on its own is not persistent; shell history is a file the person who
  did the job can delete, and an audit trail item sits in a place not under the control of the
  person who left it.
- The reproducible job count is 0/10, 0/10, and 10/10. The distinction is not between graphical
  and command but between scripted and unscripted work; the definition must sit somewhere that
  cannot be altered.
- Manual operations across forty machines drop from 400 to 10, and the place storing the change
  definition rises from 0 to 1; drift can only be asked about if a definition exists to compare
  against.
- The number of items appearing in the audit trail assumes the items sit on a common time axis
  and under common names; without these conditions, the item count does not change but the
  number of questions it answers drops.

## Next Step

Everything measured across this topic has been about how a scheme is built: which boundary
stands where, which item closes when, which policy can be expressed, which job leaves a trace.
All of it holds while the machine works as expected.

When the machine does not work as expected, only symptoms are left, and the records counted in
this lesson are where those symptoms are read. The next lesson looks at that situation and ties
the method to a number: for a set of symptoms, how many possibilities does each hypothesis
eliminate, how many steps does each sequence take to finish, and how many steps does the worst
sequence take.
